使用SQL :: Abstract时在where子句中对列进行排序

时间:2010-09-22 14:26:58

标签: sql perl

我一直在阅读Perl Hacks书中的一些食谱。方法#24“在没有SQL的情况下动态查询数据库”看起来很有趣。我们的想法是使用SQL-Abstract为您生成SQL语句。

生成select语句的语法如下所示:

my($stmt, @bind) = $sql->select($table, \@fields, \%where, \@order);

为了进一步说明,一个例子看起来像这样(取自perldoc):

my %where = (
   requestor => 'inna',
   worker => ['nwiger', 'rcwe', 'sfz'],
   status => { '!=', 'completed' }
);
my($stmt, @bind) = $sql->select('tickets', '*', \%where);

上面会给你这样的东西:

$stmt = "SELECT * FROM tickets WHERE
            ( requestor = ? ) AND ( status != ? )
            AND ( worker = ? OR worker = ? OR worker = ? )";
@bind = ('inna', 'completed', 'nwiger', 'rcwe', 'sfz');

然后您可以在DBI代码中使用它,如下所示:

my $sth = $dbh->prepare($stmt);
$sth->execute(@bind);

现在,有时WHERE子句中列的顺序非常重要,特别是如果要充分利用索引。

但是,由于SQL-AbstractWHERE子句生成器的列是通过散列指定的 - 并且众所周知,无法保证从perl散列中检索数据的顺序 - 你似乎失去了指定列顺序的能力。

我错过了什么吗?在使用SQL-Abstract时,是否有其他工具可以保证列在WHERE子句中出现的顺序?

2 个答案:

答案 0 :(得分:3)

我最初误解了你的问题。

您可以使用-and来实现所需的排序。

例如:

#!/usr/bin/perl

use strict; use warnings;

use SQL::Abstract;

my $sql = SQL::Abstract->new;

my ($stmt, @bind) = $sql->select(
    tickets => '*',
    {
        -and => [
            requestor => 'inna',
            status => { '!=', 'completed' },
            worker => ['nwiger', 'rcwe', 'sfz'],
        ],
    }
);

print "$stmt\n";

请参阅Nested conditions, -and/-or prefixes

答案 1 :(得分:0)

这个模块无法完成所有工作 - 它可以方便地构建将在“大部分时间”完成工作的查询。有时您可能仍需要手动编写查询。我在我的主$ work :: app中使用SQL :: Abstract,并且从未遇到过您描述的情况。一个好的SQL引擎将知道哪些键被索引,并优化查询以便首先使用它们,无论您指定的顺序如何。您确定您的引擎不一样,并且您在查询中指定的顺序非常重要吗?

如果您确实需要以特殊顺序订购WHERE子句,您可能会发现更容易编写子查询。 SQL :: Abstract也可以使这更容易。