MySQL更新使用PDO和预处理语句不起作用

Lor*_*con 11 php mysql pdo

我的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 +占位符处理的每个表的第一列.

Hec*_*ksa 8

http://php.net/manual/en/pdo.prepare.php说明:

调用PDOStatement :: execute()时,必须为要传递给语句的每个值包含唯一的参数标记.除非启用了仿真模式,否则不能在预准备语句中多次使用同名的命名参数标记.

如此所示,代码在一个服务器而不是另一个服务器上运行的可能原因PDO::ATTR_EMULATE_PREPARES是在代码失败的服务器上禁用了该代码.正如文档所述,此属性有效地消除了限制,阻止您使用两次相同名称的参数标记(以及其他一些限制).