sch*_*itz 1 mysql perl placeholder dbi
我有两个MySQL数据库,number1和numbers2,两者都是这样的:
+--------+
| number |
+--------+
| -5 |
+--------+
Run Code Online (Sandbox Code Playgroud)
但是,numbers1具有VARCHAR列,而numbers2具有INT列.
此代码成功打印number2的"number is:-5",但number1失败:
my $high_number = -2;
my $sql = "select * from numbers1 where number < ?";
my $sth = $dbh->prepare($sql);
$sth->execute($high_number);
while (my @row = $sth->fetchrow_array){
print "number is: $row[0]\n";
}
Run Code Online (Sandbox Code Playgroud)
但是,如果我删除占位符并直接替换:
my $sql = "select * from numbers1 where number < $high_number";
Run Code Online (Sandbox Code Playgroud)
代码适用于number1和numbers2.
因此,罪魁祸首必须是DBI的占位符,它以某种方式打破了负数的mysql查询(奇怪的正数工作得很好!)为什么DBI占位符在这里打破负数?
请注意,这与此尚未解决的2007 PerlMonks线程中遇到的问题相同.
这是因为MySQL正在进行字符串比较,字符串"-5"大于字符串"-3",即使数字-5小于数字-3.您正在经历的行为是预期的,它不会像您声称的那样"破碎".
使用占位符时,绑定值是字符串的字符串,因为列类型是varchar.没有占位符的查询在右侧有一个整数.换句话说,下面的两个查询可以理解地产生不同的结果:
select * from numbers1 where number < '$high_number';
select * from numbers1 where number < $high_number;
Run Code Online (Sandbox Code Playgroud)
如果您真的想这样做,并且想要使用占位符,则可以使用显式类型转换:
my $sql = "SELECT * FROM numbers1 WHERE
CAST(number AS SIGNED INTEGER) < CAST(? AS SIGNED INTEGER)";
Run Code Online (Sandbox Code Playgroud)