19

PDO INSERT および UPDATE 準備済みステートメントを INSERT および ON DUPLICATE KEY UPDATE に切り替えたいのですが、現在行っていることよりもはるかに効率的であると思いますが、正しい構文を理解するのに苦労しています名前付きプレースホルダーおよび bindParam と共に使用します。

SO で同様の質問をいくつか見つけましたが、PDO は初めてで、コードを自分の基準にうまく適合させることができませんでした。これは私が試したものですが、機能しません (挿入も更新もされません):

try { 
  $stmt = $conn->prepare('INSERT INTO customer_info (user_id, fname, lname) VALUES(:user_id, :fname, :lname)'          
 'ON DUPLICATE KEY UPDATE customer_info SET fname= :fname, 
                                            lname= :lname   
                                            WHERE user_id = :user_id'); 
  $stmt->bindParam(':user_id', $user_id);  
  $stmt->bindParam(':fname', $_POST['fname'], PDO::PARAM_STR);
  $stmt->bindParam(':lname', $_POST['lname'], PDO::PARAM_STR);      
  $stmt->execute();
}

これは私のコードの単純化されたバージョンです (いくつかのクエリがあり、各クエリには 20 ~ 50 のフィールドがあります)。現在、最初に更新し、更新された行数が 0 より大きいかどうかを確認し、そうでない場合は Insert を実行しています。これらのクエリにはそれぞれ独自の bindParam ステートメントのセットがあります。

4

2 に答える 2

26

ON DUPLICATE KEY構文が正しくありません。

$stmt = $conn->prepare('INSERT INTO customer_info (user_id, fname, lname) VALUES(:user_id, :fname, :lname)
    ON DUPLICATE KEY UPDATE fname= :fname2, lname= :lname2');

$stmt->bindParam(':user_id', $user_id);  
$stmt->bindParam(':fname', $_POST['fname'], PDO::PARAM_STR);
$stmt->bindParam(':lname', $_POST['lname'], PDO::PARAM_STR);      
$stmt->bindParam(':fname2', $_POST['fname'], PDO::PARAM_STR);
$stmt->bindParam(':lname2', $_POST['lname'], PDO::PARAM_STR);      

テーブル名や句を入れる必要はなくSET、句ON DUPLICATE KEYも必要ありませんWHERE(常にレコードを重複キーで更新します)。

http://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.htmlを参照してください。

また、PHP 構文エラーもありました。クエリを 2 つの文字列に分割しました。

アップデート:

複数のパラメータをバインドするには:

function bindMultiple($stmt, $params, &$variable, $type) {
  foreach ($params as $param) {
    $stmt->bindParam($param, $variable, $type);
  }
}

次に、それを呼び出します。

bindMultiple($stmt, array(':fname', ':fname2'), $_POST['fname'], PDO::PARAM_STR);
于 2012-12-30T07:52:49.593 に答える
22

以下の私見は、これに再び遭遇した人にとって正しい答えです。
注: このステートメントは、user_id がテーブルの KEY であることを前提としています。

STATEMENT は確かに間違っていましたが、受け入れられた答えは完全には正しくありませんでした。

同じ値を使用して挿入および更新している (異なる値で更新していない) 場合、これはクエリの擬似コードを修正したものです。

try { 
    //optional if your DB driver supports transactions
    $conn->beginTransaction();

    $stmt = $conn->prepare('INSERT INTO customer_info (user_id, fname, lname) ' . 
                'VALUES(:user_id, :fname, :lname)' .
                'ON DUPLICATE KEY UPDATE fname=VALUES(fname), lname=VALUES(lname)');
    $stmt->bindParam(':user_id', $user_id);  
    $stmt->bindParam(':fname', $_POST['fname'], PDO::PARAM_STR);
    $stmt->bindParam(':lname', $_POST['lname'], PDO::PARAM_STR);      
    $stmt->execute();

    //again optional if on MyIASM or DB that doesn't support transactions
    $conn->commit();
} catch (PDOException $e) {
    //optional as above:
    $conn->rollback();

    //handle your exception here $e->getMessage() or something
}
于 2014-02-13T01:16:51.103 に答える