21

是否有标准方法在 SQL 查询中绑定数组(标量)?我想绑定到一个IN子句中,如下所示:

SELECT * FROM junk WHERE junk.id IN (?);

我碰巧使用Perl::DBIwhich 将参数强制转换为标量,所以我最终得到了无用的查询,例如:

SELECT * FROM junk WHERE junk.id IN ('ARRAY(0xdeadbeef)');

澄清:我把查询放在自己的.sql文件中,所以字符串已经形成。在答案提到动态创建查询字符串的地方,我可能会进行搜索和替换。

编辑:这个问题是Parameterizing a SQL IN 子句的重复?. 我最初认为它应该这样关闭,但它似乎正在积累一些好的 Perl 特定信息。

4

8 回答 8

14

如果您不喜欢那里的地图,可以使用“x”运算符:

my $params = join ', ' => ('?') x @foo;
my $sql    = "SELECT * FROM table WHERE id IN ($params)";
my $sth    = $dbh->prepare( $sql );
$sth->execute( @foo );

'?' 周围需要括号。因为这会强制“x”在列表上下文中。

阅读“perldoc perlop”并搜索“二进制“x”以获取更多信息(位于“乘法运算符”部分)。

于 2009-02-05T11:44:15.787 回答
12

您指定“这是带有一个参数的查询的 SQL”——当您需要多个参数时,这将不起作用。当然,处理起来很痛苦。已经建议的另外两个变体:

1) 使用 DBI->quote 代替占位符。

my $sql = "select foo from bar where baz in ("
           . join(",", map { $dbh->quote($_) } @bazs)
           . ")";
my $data = $dbh->selectall_arrayref($sql);

2)使用 ORM 为你做这种低级的事情。例如 DBIx::Class 或 Rose::DB::Object。

于 2009-02-05T04:29:32.920 回答
9

我做类似的事情:

my $dbh = DBI->connect( ... );
my @vals= ( 1,2,3,4,5 );
my $sql = 'SELECT * FROM table WHERE id IN (' . join( ',', map { '?' } @vals ) . ')';
my $sth = $dbh->prepare( $sql );
$sth->execute( @vals );
于 2009-02-05T00:53:00.720 回答
6

还有另一种构建 SQL 的方法是使用类似SQL::Abstract ....

use SQL::Abstract;
my $sql    = SQL::Abstract->new;
my $values = [ 1..3 ];
my $query  = $sql->select( 'table', '*', { id => { -in => $values } } );

say $query;   # => SELECT * FROM table WHERE ( id IN ( ?, ?, ? ) )
于 2009-02-05T20:17:28.153 回答
4

使用plain DBI,您必须自己构建SQL,如上所述。DBIx::Simple(一个包装器DBI)自动使用'??'为你做这件事 符号:

$db->query("select * from foo where bar in (??)", @values);
于 2009-02-05T11:25:08.227 回答
2

在 python 中,我总是最终做了类似的事情:

query = 'select * from junk where junk.id in ('
for id in junkids:
  query = query + '?,'
query = query + ')'

cursor.execute(query, junkids)

...它本质上是用一个“?”构建一个查询。对于列表的每个元素。

(如果那里也有其他参数,则需要确保在执行查询时正确排列)

[编辑以使非 python 人员更容易理解代码。有一个错误,查询将在最后一个 ? 之后有一个额外的逗号,我将保留它,因为修复它只会模糊总体思路]

于 2009-02-04T23:22:25.320 回答
0

我使用DBIx::DWIW。它包含一个名为 InList() 的函数。这将创建列表所需的 SQL 部分。但是,这仅在您将所有 SQL 都放在程序中而不是在单独的文件中时才有效。

于 2009-02-05T12:57:49.243 回答
0

采用

SELECT * FROM junk WHERE junk.id = ANY (?);

反而

于 2017-05-31T13:08:45.430 回答