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

时间:2012-02-09 11:02:49

标签: 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;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);

在第三种情况下,在我的服务器上,没有对行执行更新,没有任何原因或异常/错误。在另一台服务器上它工作。我不是在寻找像这样的答案:“等等?使用第一个或第二个实现”:)

我问为什么第三个实现不起作用,因为我正在将大量代码从服务器迁移到另一个(它不是我的代码)并且它包含大量查询喜欢这个,我没有时间一个一个地修复它们。在当前的服务器上它可以工作,在新的服务器上它没有。

为什么第三个实现不起作用? 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);

在两台服务器上执行此代码(工作和不工作):

PDOStatement Object
(
    [queryString] => update test_table set id=:id, value=:value where id=:id
)
Array
(
    [0] => 00000
    [1] => 
    [2] => 
)

更新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)
);

难以置信,不是吗?我现在怀疑存在一些特殊的更新beahaviour专门针对PDO +占位符处理的每个表的第一列

3 个答案:

答案 0 :(得分:8)

http://php.net/manual/en/pdo.prepare.php州:

  

您必须为您希望的每个值包含唯一的参数标记   调用PDOStatement :: execute()时传入语句。 您   不能多次使用同名的命名参数标记   准备好的声明,除非启用仿真模式。

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

答案 1 :(得分:-1)

try {
     $db = new PDO('mysql:host=localhost;dbname=vendor_management_system', 'root', '');
     $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
     $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false);
}catch(PDOException $e) {
    echo 'ERROR: ' . $e->getMessage();
}




$fields[] = 'car_name';
$fields[] = 'model_no';
$fields[] = 'maker_id';
$fields[] = 'dealer_id';

$values[] = "testcar";
$values[] = "no#1";
$values[] = 2;
$values[] = 4;



echo SQLUpdate('car_details', $fields, $values,'car_id = 32 and car_name = "testname"',$db);




//START: SQLUpdate
//$fields = array of fields in DB
//$values = array of values respective to the $fields
 function SQLUpdate($table,$fields,$values,$where,$db) {



  //build the field to value correlation
  $buildSQL = '';
  if (is_array($fields)) {

        //loop through all the fields and assign them to the correlating $values
        foreach($fields as $key => $field) :
      if ($key == 0) {
            //first item
            $buildSQL .= $field.' = ?';
          } else {
            //every other item follows with a ","
            $buildSQL .= ', '.$field.' = ?';
          }
    endforeach;

  } else {
    //we are only updating one field
        $buildSQL .= $fields.' = :value';
  }

  $prepareUpdate = $db->prepare('UPDATE '.$table.' SET '.$buildSQL.'
WHERE '.$where);

  //execute the update for one or many values
  if (is_array($values)) {
    $affected_rows=$prepareUpdate->execute($values);
    return $affected_rows;
  } else {
    $affected_rows=$prepareUpdate->execute(array(':value' => $values));
    return $affected_rows;
  }


  //record and print any DB error that may be given
  $error = $prepareUpdate->errorInfo();
  if ($error[1]) print_r($error);

} 
//END: SQLUpdate

答案 2 :(得分:-2)

$maker_id=1;
$stmt = $db->prepare("UPDATE car_details SET maker_id=?");
$affected_rows=$stmt->execute(array($maker_id));
echo $affected_rows.' were affected';