2012-02-09 6 views
11

PHP PDOとmysqlに奇妙な問題があります。単一の行を持つ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); 

、私のサーバー上で、更新は上行われていません何らかの理由も例外/エラーもなしに行を追加します。別のサーバー上で動作します。私は次のような答えを探していません: "それで、最初の実装か2番目の実装を使用しますか?"

私はなぜサーバーから多くのコードをもう1つ(これは私のコードではない)です。このようなクエリが多数含まれており、1つずつ修正する時間がありません。現在のサーバーでは動作し、新しいサーバーでは動作しません。

なぜ3番目の実装が機能しないのですか?この動作に影響を与える可能性のある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); 

はエラーメッセージを出しsqeezeしようとしました

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

信じられないほどですか?私の容疑者は現在、PDO +プレースホルダ処理のすべてのテーブルの最初の列のために特別に作られた特別なアップデートbeahaviourが存在します。

+1

あなたが使用している:IDを両方の「ID」の値を変更するだけでなく、行を識別します。あなたはそれがあなたがしたいことだと確信していますか? – middus

+1

@middus:「私はコードをサーバーから別のコードに移行していますが、このようなクエリが多数含まれており、1つずつ修正する時間がありません」 –

+0

私は知っている、それは私のコードではない。私は決してそれをしないだろう。それでも、サーバー上で動作しない理由と、別のサーバーで動作する理由を知りたいと思います。 –

答えて

8

http://php.net/manual/en/pdo.prepare.php状態:

あなたがにPDOStatementを呼び出すときに文の中で 渡したい値ごとに独自のパラメーター・マーカーを含める必要があります::実行()。 エミュレーションモードがオンでない限り、 プリペアドステートメントで同じ名前の名前付きパラメーターマーカーを複数回使用することはできません。これが示すように

、あなたのコードが1台のサーバー上で作業をしていない別の背後にある可能性が高い理由は、PDO::ATTR_EMULATE_PREPARESコードが上の障害が発生したサーバ上で無効になっているということです。ドキュメントによれば、この属性は効果的に制限を削除して、同じ名前のパラメータマーカーを2回使用することを防ぎます(その他の制限もあります)。

+0

まあ、答えはありません、実際は:)しかし、ありがとう –

+0

それは部分的な答えです:P私はもっと何かを描くなら、私はそれを更新しますが、私は今はどこにもいません。正直言って、それがいつもうまくいくのか分からない。 – Hecksa

+0

うん..なぜか?テストテーブルのmysqlコンソール上でrawアップデートを試してみると、それは動作します(例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 
+0

答えがこの質問に追加された内容やコードの内容を説明してください。 – Kermit

-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'; 
+2

この質問に回答が追加されたことや、コードが何をしているのか説明してください。 – Kermit

関連する問題