Perl中对查询得的数据排序。

类别:软件工程 点击:0 评论:0 推荐:

昨天晚上遇到这么个问题,客户反映我们的一个页面的排序不正确,对方反映了几次,可是我们就是什么问题都没查出来,看看查询的SQL命令,完全按照要求排序了呀,怎么会不正确呢。
对方看我们迟迟无法解决,也是非常着急,并把他们那里出现的错误画面发过来了,于是晚上我抱着试试看的想法,把用户提供的数据输入到我们的系统中,刚开始输了几个,排序完全正常,然后,当我输入了十几条数据后,竟然发现排序确实不正常的。而乍一看我们的代码也没有任何问题:

# データベースからデータを検索する。
# @param $query
# @return $recordset(HashのPointer)、または0。
# db_select_hashと違う点は:この関数の戻り値のKeyは順序の数字です
# ex:
#   use chira::db;
#   my $rset = db_select_hash2("select owner_id, owner_name from ec02");
#   if (! $rset) {
#       print "Error when select";
#   }
#   else {
#       my $key;
#       foreach $key (sort keys %$rset) {
#           my $arrpoint = $$rset{$key};
#           print "$key = $$arrpoint[0], $$arrpoint[1]\n";
#       }
#   }
sub db_select_hash2($)
{
    my $query = shift;
    my %aux;
    $query = escapesql($query);
    eval {
        my $sth = $dbh -> prepare($query);
        $sth->execute;
        my @row;
        my $id = 0;
        while (@row = $sth->fetchrow_array) {
            $aux{$id} = [@row];
            $id ++;
        }
    };
    if ($@) {
        lg_adddebug("_select_hash2: " . $query, "db.pm");
        return 0;
    }
    else {
        return \%aux;
    }
}

$rows = &db_select_hash2("select ec91.DISP_NO, ec91.CATEG_ID, ec91.CATEG_NAME, ec91.SHOP_CNT from ec91 where $owner_id=EC91.OWNER_ID order by EC91.DISP_NO ASC, EC91.CATEG_ID ASC");

foreach $key (sort keys %$rows) {
......
}

其中db_select_hash2()函数是对数据库进行查询,并将查询结果按照次序放在一个hash表中,hash表的key为一个自增型的数字。
在外部程序的foreach()循环中,自动按照这个key为顺序,一一返回所有查询得的纪录。
难道是foreach()的地方发生了问题?
于是我将foreach中的$key一一打印出来,一看,呵呵,原来问题出现在这里。。我们希望的结果应该是:
0,1,2,。。。,8,9,10,11,12
但实际却变为:
0,1,10,11,12,。。。,2,3
原来如此,foreach()中的sort按照ascii来对hash表进行排序了,当然,只要让它按照数字来排就能解决问题,可是,我在网上搜索了半天,又翻了本大砖头,还是一无所获,眼看一个晚上就要过去,今天可是必须release的,没办法,急中生智,我用了这么一招:

sub db_select_hash2($)
{
    my $query = shift;
    my %aux;
    $query = escapesql($query);
    eval {
        my $sth = $dbh -> prepare($query);
        $sth->execute;
        my @row;
        my $id = 0;
        while (@row = $sth->fetchrow_array) {
            #$aux{$id} = [@row];
            #modified by tony
            # else the foreach() will sort the key like (0, 1, 10, 11, 2, 3, 4 ...)
            my $key = "00000" . $id;
            $key = substr($key, length($key)-5, 5);
            $aux{$key} = [@row];
            $id ++;
        }
    };
    if ($@) {
        lg_adddebug("_select_hash2: " . $query, "db.pm");
        return 0;
    }
    else {
        return \%aux;
    }
}

我将key
1,2,3。。。,9,10,11
变成了这样:
00001,00002,00003。。。,00009,00010,00011
这样在ascii排序方式下,也总能返回正确顺序了。

虽然问题暂时解决了,但是用了这种恶心的招数,实在是有愧于perl啊,只希望各位perl大虾不要笑话。

另外,本次事件也让我再次深刻的认识到,软件上的很多问题,其实都是可以经过更广泛的测试来避免的,这就体现出引入自动化测试的必要性了,对于有些页面之类很难用自动化来完成的测试工作,则应该使用相对比较无序的数据来进行测试。

本文地址:http://com.8s8s.com/it/it32592.htm