我的php PDO和mysql有一个奇怪的问题.
我有下表:
create table test_table ( id integer, value text );
Run Code Online (Sandbox Code Playgroud)
单排:
insert into test_table values (1, "asdf");
Run Code Online (Sandbox Code Playgroud)
当我尝试使用预准备语句更新此单行时,根据我使用的语法,我得到了不同的行为:
// connection to db (common code)
$dbh = new PDO("mysql:host=localhost;dbname=test", "myuser", "mypass");
Run Code Online (Sandbox Code Playgroud)
================================================== =======
// WORKING
$q = 'update test_table set id=1, value='.rand(0,99999).' where id=1';
$dbh->exec($q);
Run Code Online (Sandbox Code Playgroud)
================================================== =======
// WORKING
$q = 'update test_table set value=:value where id=:id';
$par = array(
"id" => 1,
"value" => rand(0,99999)
);
$sth = $dbh->prepare($q, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute($par);
Run Code Online (Sandbox Code Playgroud)
================================================== =======
// NOT WORKING
$q = 'update test_table set id=:id, value=:value where id=:id';
$par = array(
"id" => 1,
"value" => rand(0,99999)
);
$sth = $dbh->prepare($q, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
$sth->execute($par);
Run Code Online (Sandbox Code Playgroud)
在第三种情况下,在我的服务器上,没有在行上执行更新,没有任何原因或异常/错误.在另一台服务器上它工作.我不是在寻找像这样的答案:"等等?使用第一个或第二个实现":)
我问为什么第三个实现不起作用,因为我将大量代码从服务器迁移到另一个(这不是我的代码),它包含很多像这样的查询,我没有时间修复他们一个接一个.在当前的服务器上它工作,而在新的服务器上它不工作.
为什么第三个实现不起作用?是否有任何形式的php/pdo/mysql可能会影响这种行为?
谢谢.
更新: 尝试sqeeze出错信息:
$dbh->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION );
try {
// NOT WORKING
$q = 'update test_table set id=:id, value=:value where id=:id';
$par = array(
"id" => 1,
"value" => rand(0,99999)
);
$sth = $dbh->prepare($q, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
print_r($sth);
print_r($dbh->errorInfo());
} catch(PDOException $e) {
echo $e->getMessage();
}
$sth->execute($par);
Run Code Online (Sandbox Code Playgroud)
在两台服务器上执行此代码(工作和不工作):
PDOStatement Object
(
[queryString] => update test_table set id=:id, value=:value where id=:id
)
Array
(
[0] => 00000
[1] =>
[2] =>
)
Run Code Online (Sandbox Code Playgroud)
更新2
看看这个进一步的测试:
create table test_table ( value0 text, value text );
insert into test_table values ("1", "pippo");
// NOT WORKING
$q = 'update test_table set value0=:value0, value=:value where value0=:value0';
$par = array(
"value0" => "1",
"value" => rand(0, 839273)
);
create table test_table ( value0 text, value text );
insert into test_table values ("pippo", "1");
// WORKING
$q = 'update test_table set value=:value, value0=:value0 where value=:value';
$par = array(
"value" => "1",
"value0" => rand(0, 839273)
);
Run Code Online (Sandbox Code Playgroud)
难以置信,不是吗?我现在怀疑的是,存在一些特殊的更新beahaviour专门针对PDO +占位符处理的每个表的第一列.
http://php.net/manual/en/pdo.prepare.php说明:
调用PDOStatement :: execute()时,必须为要传递给语句的每个值包含唯一的参数标记.除非启用了仿真模式,否则不能在预准备语句中多次使用同名的命名参数标记.
如此所示,代码在一个服务器而不是另一个服务器上运行的可能原因PDO::ATTR_EMULATE_PREPARES
是在代码失败的服务器上禁用了该代码.正如文档所述,此属性有效地消除了限制,阻止您使用两次相同名称的参数标记(以及其他一些限制).