2010-09-22 51 views
2

我一直在阅读Perl Hacks书中的一些食谱。配方#24“无SQL查询数据库动态”看起来很有趣。这个想法是使用SQL-Abstract为你生成SQL语句。使用SQL时where子句中列的排序::摘要

生成一个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代码中使用s ○:

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

现在,有时WHERE子句中的列的顺序是非常重要的,特别是如果你想用好指标。

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

我错过了什么?当使用SQL-Abstract时,是否有备用设施来保证列出现在WHERE子句中的订单?

回答

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

+0

谢谢你,达到了预期的效果! – 2010-09-23 06:45:23

0

这个模块不能做所有事情 - 这是为了构建能够在“大部分时间”完成这项工作的查询的便利。有时你仍然可能需要手工编写查询。我在我的主要$ work :: app中使用SQL :: Abstract,并且从未遇到过描述的情况。一个好的SQL引擎将知道哪些键被索引,并优化查询以便首先使用这些键,而不管您指定的顺序如何。你确定你的引擎不一样,并且你在查询中指定的顺序真的很重要吗?

如果您确实需要按照特殊顺序排列WHERE子句,则可能会发现编写子查询更容易。 SQL :: Abstract也可以使这更简单。

+0

谢谢,我没有考虑过SQL引擎会优化查询以使用索引的键。在mysql中,似乎还有一个额外的约束:“如果列没有形成索引的最左边的前缀,MySQL就不能使用索引” - 因此,至少WHERE子句的这部分排序必须得到保证(请参阅http ://dev.mysql.com/doc/refman/5.0/en/mysql-indexes.html)。 – 2010-09-23 06:52:02