2

我有这个奇怪的问题。为什么这两个实现返回不同的结果?

    $db = DbBase::getInstance();
    $stmt = $db->prepare('SELECT round(round(9.50 * :amount, 2) * 23 * 0.01, 2)');
    $stmt->execute(array(':amount' => 1));
    echo $stmt->fetchColumn();

    Result: 2.18

    $db = DbBase::getInstance();
    $stmt = $db->prepare('SELECT round(round(9.50 * 1, 2) * 23 * 0.01, 2)');
    $stmt->execute();
    echo $stmt->fetchColumn();

    Result: 2.19

当我绑定金额时,它会给我不同的结果。由于 SQL 注入,我宁愿不连接字符串。

4

1 回答 1

4

当您使用数组传递数据时,数据作为字符串传递:

文档

一个包含与正在执行的 SQL 语句中的绑定参数一样多的元素的值数组。所有值都被视为 PDO::PARAM_STR。

但是,当您直接手动输入1查询时,它被视为 int。让我看看我是否可以做一些进一步的挖掘,看看当一个字符串为你转换成一个 int 时内部会发生什么。

编辑:这可能是已提交并接受的最相似的错误之一:

1)
SET @a = 1;
SELECT @a;

2)
SET @a = 1.1;
SELECT @a;

.. and this 

3)
SET @a = 1.1;
SELECT @a + 7;
returns '8.100000000000000000000000000000'
(probably the addition will convert "1.1" to a double, the result 
of the addition is also a DOUBLE and finally the DOUBLE is converted 
to a string - that should be OK as well as far as I can understand)

因此,当您将 int 传递给 mysql 时,它看起来就像在内部转换为 double 类型。这将很好地解释您所看到的行为。

以下是您可能感兴趣的其他类似(数字不太正确)错误的列表:

http://bugs.mysql.com/bug.php?id=46037

http://bugs.mysql.com/bug.php?id=35071

http://bugs.mysql.com/bug.php?id=35071 <-- 很好的显示 Win 和 Lin 之间的区别

以及我细读的数据类型错误的过滤列表,这些错误使阅读变得有趣。

编辑2:啊哈!

这是一个可以完美解释您的问题的错误:

Reproduce code:
---------------
CREATE TABLE my_db.my_table (
  id int(10) unsigned NOT NULL auto_increment,
  PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=utf8;

<?php
$DB = new PDO('mysql:dbname=my_db;host=localhost', 'user', 'pass');
$stmt = $DB->prepare('select * from my_table where id>?');
$stmt->bindValue(1, 13);
$stmt->execute();
?>

or

<?php
$DB = new PDO('mysql:dbname=my_db;host=localhost', 'user', 'pass');
$stmt = $DB->prepare('select * from my_table where id>?');
$stmt->execute(array(13));
?>

Expected result:
----------------
select * from my_table where id>13

Actual result:
--------------
select * from my_table where id>'13'
于 2012-08-28T08:35:19.820 回答