我有这个查询select * from table where ID in (1,2,3,5...)
如何使用占位符与DBI构建此查询?
例如:
my @list = (1, 2, 3, 4, 5);
my $sql = "select * from table where ID in (?)";
$sth->prepare($sql);
$sth->execute();
我应该发送什么参数来执行?它是由,
或其他东西分隔的列表或字符串吗?
答案 0 :(得分:28)
这应该根据数组中项目的数量动态构建查询
my @list =(1,2,3,4,5);
my $sql ="select * from table where ID in (@{[join',', ('?') x @list]})";
答案 1 :(得分:11)
以这种方式是不可能的。您需要为数组中的每个项指定占位符:
my @list = (1,2,3,4,5);
my $sql = "select * from table where ID in (?,?,?,?,?)";
$sth->prepare($sql);
$sth->execute(@list);
如果您的@list
不是固定大小,则需要使用适当数量的占位符构建$sql
。
答案 2 :(得分:6)
此外,占位符只能表示单个标量值。例如,以下语句将无法按预期工作 对于多个值:
SELECT name, age FROM people WHERE name IN (?) # wrong SELECT name, age FROM people WHERE name IN (?,?) # two names
重写为:
my $sql = 'select * from table where ID in ( ?, ?, ?, ?, ? )';
$sth->prepare($sql);
$sth->execute(@list);
答案 3 :(得分:2)
如果您使用DBI使用DBD :: Pg驱动程序访问PostgreSQL数据库,您可以使用:
my @list = (1, 2, 3, 4, 5);
my $sql = "select * from table where ID = ANY(?::INT[]);";
$sth->prepare ($sql);
$sth->execute (\@list);
答案 4 :(得分:1)
如果切换到DBIx::Simple,您只需说:
$db->query('INSERT INTO foo VALUES (??)', $foo, $bar, $baz);
??意味着“尽可能多的”
修改强>
实际上,我有点过于乐观了:“如果查询中存在字符串(??),则会将其替换为与@values一样多的问号列表。” < / p>
所以这似乎不起作用:
$db->query( "SELECT * FROM foo WHERE id IN (??) AND stuff=?", @ids, $stuff )
虽然仍然有用..
好奇的是,模块中的代码是:
# Replace (??) with (?, ?, ?, ...)
sub _replace_omniholder {
my ($self, $query, $binds) = @_;
return if $$query !~ /\(\?\?\)/;
my $omniholders = 0;
my $q = $self->{dbd} =~ /mysql/ ? $quoted_mysql : $quoted;
$$query =~ s[($q|\(\?\?\))] {
$1 eq '(??)'
? do {
Carp::croak('There can be only one omniholder')
if $omniholders++;
'(' . join(', ', ('?') x @$binds) . ')'
}
: $1
}eg;
}
答案 5 :(得分:1)
除非您知道元素的确切数量,否则不能使用占位符。试试这个:
my @list = (1, 2, 3, 4, 5); # any number of elements
my $in = join(',', map { $dbh->quote($_) } @list);
my $sql = "select * from table where someid IN ($in)";
答案 6 :(得分:0)
我找到了一个确定的方法来总结所有上述建议。我的生产查询(我在这里发布了一个更简单的版本)使用IN&lt;&gt;,其中代码及其数量都未知。它可以是单个代码(例如FIN
),也可以是一系列代码(FITLC FITLD FITLU FITSC FITSD FITSU MDYLC MDYLD MDYLU
)。某些函数将其作为列表返回。
实现这一目标的代码是
@codes = get_muni_evcode( $category );
my $in = join( ', ', ('?') x @codes );
print "\n\nProcessing Category: $category --> Codes: @codes .. in: $in\n";
my $sql = "select distinct cusip9
from material_event
where event_date between (trunc(sysdate) - 1) + 2/3 and trunc(sysdate) + 2/3
and event_code in ($in)";
my $sth2 = $dbh->prepare($sql);
$sth2->execute( @codes );
while (my $s2 = $sth2->fetchrow_hashref('NAME_lc'))
{
my $cusip9 = $s2->{cusip9};
print "$cusip9\t";
.................. further processing ..............
}
结果样本:
Processing Category: RatingChange --> Codes: FITLC FITLD FITLU FITSC FITSD FITSU MDYLC MDYLD MDYLU MDYSC MDYSD MDYSU SPLD SPLPR SPLU SPSD SPSPR SPSU .. in: ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?
359496HQ2 359496GB6 359496GH3 359496GL4 359496HU3 359496HS8 359496HA7 359496HF6 359496GM2 359496HM1 359496HR0 359496HT6 359496GY6 359496GJ9 359496HL3 359496GU4 359496HK5 359496HN9 359496HP4 359496GW0 359496GZ3 359496HC3 359496GC4 359496GK6 359496GP5 359496GV2 359496GX8 359496GN0
我非常感谢在这里发表意见的所有人,这终于让我找到了正确的方法。我认为这一定是一个非常普遍的问题。