好的。我可能在这里很厚实(众所周知),但是我是否在 PHP 5.3.x 中的 MySQLi 中发现了准备好的语句的未记录“功能”,或者我错过了一些非常基本的东西。
简短版- 通过 MySQLi 和 mysqlnd 驱动程序在 PHP 中准备的语句返回不正确的浮点值
长版
首先是一些测试数据
mysql> CREATE TABLE `t2` (`v` float(6,2) NOT NULL DEFAULT '0.00');
Query OK, 0 rows affected (0.08 sec)
mysql> insert into t2 (v) values (0.03);
Query OK, 1 row affected (0.00 sec)
通过准备好的语句检索上述值时会出现问题。当使用旧的 mysql_... 或标准 mysqli... 查询调用时,会返回正确的数据。但是,通过准备好的语句使用相同的查询会返回错误的值:
测试代码:
atom:~/testScripts> cat f1.php
<?php
require('passwds.php');
$q="select * from t2"; // same query for all
echo "/* Old style MySQL statements (deprecated) */".PHP_EOL;
$h1=mysql_connect(MYSQL_SERVER,MYSQL_USER,MYSQL_PASSWORD);
mysql_select_db('test',$h1);
$r1=mysql_query($q);
while ($f1=mysql_fetch_assoc($r1))
{
echo print_r($f1,true).PHP_EOL;
}
echo "/* New style MySQLi statements */".PHP_EOL;
$h2=new mysqli(MYSQL_SERVER,MYSQL_USER,MYSQL_PASSWORD,'test');
$r2=$h2->query($q);
while ($f2=$r2->fetch_assoc())
{
echo print_r($f2,true).PHP_EOL;
}
echo "/* New style MySQLi prepared statements */".PHP_EOL;
$h3=new mysqli(MYSQL_SERVER,MYSQL_USER,MYSQL_PASSWORD,'test');
$s3=$h3->stmt_init();
$s3->prepare($q);
$s3->execute(); // no binding required
$r3=$s3->get_result();
while ($f3=$r3->fetch_assoc())
{
echo print_r($f3,true).PHP_EOL;
}
结果:
atom:~/testScripts> php -f f1.php
/* Old style MySQL statements (deprecated) */
Array
(
[v] => 0.03
)
/* New style MySQLi statements */
Array
(
[v] => 0.03
)
/* New style MySQLi prepared statements */
Array
(
[v] => 0.029999999329448
)
如果我将v
表中的类型更改t2
为 aDOUBLE
而不是FLOAT
a 准备好的语句返回的值是正确的。
在 Linux 机器上运行脚本(OpenSuse 12.1 32 位,MySQL 和 PHP 从源代码编译)和 Windows 7(64 位,从二进制文件安装 PHP,数据来自 Linux 机器)时,我得到相同的响应。我还在 OpenSuse 12.1 64 位安装(同样,PHP 和 MySQL 使用 mysqlnd 驱动程序从源代码安装)上进行了尝试,结果相同。所有版本都使用mysqlnd
PHP 提供的驱动程序
问题我是否遗漏了一些非常基本的东西,还是应该向 PHP.NET 报告错误?
抱歉,这是一个很长的问题,但我想我会提供尽可能多的数据