问题
I have this weird problem. Why do these two implementations return different results?
$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
When I bind the amount it gives me different result. I'd rather not concatenate the string because of the SQL injections.
回答1:
When you are using the array to pass the data, the data is passed as a string:
From the docs:
An array of values with as many elements as there are bound parameters in the SQL statement being executed. All values are treated as PDO::PARAM_STR.
However, when you are manually entering in the 1 into the query directly it is being treated as an int. Let me see if I can do some further digging to see what happens internally when a string is converted into an int for you.
Edit: This is probably one of the most similar bugs that have been submitted and accepted:
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)
So it looks like internally mysql is converting to a double when you pass it an int. That would explain rather nicely the behavior that you are seeing.
Here is a list of other similar (numbers not quite right) bugs you might be interested in:
http://bugs.mysql.com/bug.php?id=46037
http://bugs.mysql.com/bug.php?id=35071
http://bugs.mysql.com/bug.php?id=35071 <-- Good one showing difference between Win and Lin
And a filtered list of data type bugs that I perused which make for interesting reading.
Edit 2: Aha!
Here is a bug that rather perfectly explains your issue:
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'
来源:https://stackoverflow.com/questions/12155465/pdo-difference-between-binding-params-and-concatenating-string