Php 使用PDO和prepared语句的MySQL更新不起作用

Php 使用PDO和prepared语句的MySQL更新不起作用,php,mysql,pdo,Php,Mysql,Pdo,我在php PDO和mysql方面遇到了一个奇怪的问题 我有下表: create table test_table ( id integer, value text ); 对于单行: insert into test_table values (1, "asdf"); 当我试图用一个准备好的语句更新这一行时,我会根据我使用的语法得到不同的行为: // connection to db (common code) $dbh = new PDO("mysql:host=localhost;dbn

我在php PDO和mysql方面遇到了一个奇怪的问题

我有下表:

create table test_table ( id integer, value text );
对于单行:

insert into test_table values (1, "asdf");
当我试图用一个准备好的语句更新这一行时,我会根据我使用的语法得到不同的行为:

// connection to db (common code)
$dbh = new PDO("mysql:host=localhost;dbname=test", "myuser", "mypass");
=========================================================

// WORKING
$q = 'update test_table set id=1, value='.rand(0,99999).' where id=1';
$dbh->exec($q);
// 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);
// 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);
=========================================================

// WORKING
$q = 'update test_table set id=1, value='.rand(0,99999).' where id=1';
$dbh->exec($q);
// 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);
// 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);
=========================================================

// WORKING
$q = 'update test_table set id=1, value='.rand(0,99999).' where id=1';
$dbh->exec($q);
// 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);
// 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);
在第三种情况下,在我的服务器上,在没有任何原因或异常/错误的情况下,不会对行执行更新。在另一台服务器上它可以工作。我不是在寻找这样的答案:“那么呢?使用第一个或第二个实现”:

我在问为什么第三个实现不起作用,因为我正在将大量代码从一台服务器迁移到另一台服务器(这不是我的代码),它包含大量类似于此的查询,我没有时间逐一修复它们。在当前服务器上它工作,而在新服务器上它不工作

为什么第三个实现不起作用?是否有任何类型的php/pdo/mysql配置会影响这种行为

谢谢

更新: 试图清除错误消息:

$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);
在两台服务器上执行此代码(工作和不工作):

更新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)
);
难以置信,不是吗?我现在怀疑存在一些专门针对PDO+占位符处理中每个表的第一列的特殊更新行为。

声明:

您必须为希望输入的每个值包含一个唯一的参数标记 调用PDOStatement::execute()时传入语句<斯特朗>你 在中不能多次使用同名的命名参数标记 准备好的语句,除非仿真模式已打开。


如上所述,代码在一台服务器上工作而不是在另一台服务器上工作的原因可能是,在代码出现故障的服务器上禁用了
PDO::ATTR\u EMULATE\u PREPARES
。正如文档所述,该属性有效地消除了阻止您两次使用相同名称的参数标记的限制(以及一些其他限制)

您正在使用:id来更改“id”的值以及标识行。你确定这就是你想要做的吗?@middus:正如他所说:“我正在将大量代码从一台服务器迁移到另一台服务器(不是我的代码),其中包含大量类似于此的查询,我没有时间逐一修复它们。”我知道,这不是我的代码。我决不会那样做。不过,我还是想知道为什么它在一台服务器上不工作,而在另一台服务器上工作。那么,这两台服务器之间还有什么不同之处吗?也许一个数据库在id上有一个索引,而另一个没有,或者你能想到的其他任何东西?正如你所说,考虑到这些版本,mysql版本似乎不可行。这是一个部分答案:P如果我有更多的想法,我会更新它,但我现在一事无成。老实说,我不明白为什么它会起作用。。为什么不呢?如果您在测试表的mysql控制台上尝试一个原始更新,它就会工作(示例1)。只有用占位符替换值时才会出现问题。正如答案中所解释的,是使用PDO导致了问题。不允许在查询中放置两次
:id
,如果希望在查询中放置两次相同的值,则需要使用另一个具有不同名称的参数(尽管包含相同的值)。例如,
updatetest\u table set id=:id,value=:value,其中id=:idCopy
可以,忘记我删除的评论。这是一个占位符问题。但最初的问题仍然旨在理解它是如何工作的。。PDO版本的错误?你能解释一下你的答案给这个问题增加了什么或者你的代码做了什么吗?你能解释一下你的答案给这个问题增加了什么或者你的代码做了什么吗?