【问题标题】:Why do Perl's DBI placeholders break for negative number MySQL queries?为什么 Perl 的 DBI 占位符会因负数 MySQL 查询而中断?
【发布时间】:2015-05-27 07:05:14
【问题描述】:

我有两个 MySQL 数据库,numbers1 和 numbers2,它们看起来都是这样的:

+--------+
| number |
+--------+
|     -5 |
+--------+

但是,numbers1 有一个 VARCHAR 列,而 numbers2 有一个 INT 列。

此代码成功为 numbers2 打印“number is: -5”,但为 numbers1 打印失败:

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";
}

但是,如果我删除占位符并直接替换:

my $sql = "select * from numbers1 where number < $high_number";

该代码适用于 numbers1 和 numbers2。

因此,罪魁祸首一定是 DBI 的占位符,它以某种方式破坏了 mysql 对负数的查询(奇怪的是正数工作得很好!)为什么 DBI 占位符在这里破坏了负数?

注意,这和目前unsolved 2007 PerlMonks thread遇到的问题是一样的。

【问题讨论】:

  • 如果你有一个 VARCHAR 字段,也许你应该使用一个字符串,而不是一个数字,my $number = "-2"。这对 Perl 来说并不重要,但也许 DBI 在他们的驱动程序中有一些东西可以对其进行硬编码。您能就此对 varchar 字段进行 &lt; 比较吗?
  • 另外,总是包含错误信息。 DBI 报告什么错误?
  • 尝试了字符串表示,没有运气。是的,您可以对 VARCHAR 进行
  • 如果DBI没有报错,你怎么知道有问题? “失败”是对错误的一个非常薄弱的​​描述。
  • 哦,我明白了。当你说“失败”时,你的意思是它没有打印任何东西。在描述您的问题时,您应该始终绝对具体,在这种情况下,您应该说“它不打印任何东西”,而不是“它失败了”。

标签: mysql perl placeholder dbi


【解决方案1】:

这是因为 MySQL 正在做一个字符串比较,字符串“-5”大于字符串“-3”,即使数字 -5 小于数字 -3。您遇到的行为是预期的,它并没有像您声称的那样“损坏”。

当使用占位符时,绑定值被强制转换为字符串,因为列类型是 varchar。没有占位符的查询在右侧有一个整数。换句话说,下面的两个查询会产生不同的结果,这是可以理解的:

select * from numbers1 where number < '$high_number';
select * from numbers1 where number < $high_number;

如果你真的想这样做,并且想使用占位符,你可以使用显式类型转换:

my $sql = "SELECT * FROM numbers1 WHERE 
           CAST(number AS SIGNED INTEGER) < CAST(? AS SIGNED INTEGER)";

【讨论】:

  • 这就解释了。谢谢你的精彩解释!
  • 或更简洁地说,where number &lt; round(?)
猜你喜欢
  • 2015-08-07
  • 2015-06-22
  • 1970-01-01
  • 2010-12-13
  • 1970-01-01
  • 1970-01-01
  • 2010-12-24
  • 1970-01-01
  • 2017-05-20
相关资源
最近更新 更多