PDO为INSERT和ON DUPLICATE KEY UPDATE准备了带有命名占位符的语句

Cha*_*per 10 php pdo prepared-statement sqlbindparameter on-duplicate-key

我想将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();
}
Run Code Online (Sandbox Code Playgroud)

这是我的代码的简化版本(我有几个查询,每个查询有20-50个字段).我当前正在更新并检查更新的行数是否大于0,如果没有则运行Insert,并且每个查询都有自己的bindParam语句集.

Bar*_*mar 18

你的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);      
Run Code Online (Sandbox Code Playgroud)

您不需要将表名SET放在ON DUPLICATE KEY子句中,也不需要WHERE子句(它总是使用重复键更新记录).

请参阅http://dev.mysql.com/doc/refman/5.5/en/insert-on-duplicate.html

您还遇到了PHP语法错误:将查询拆分为两个字符串.

更新:

绑定多个参数:

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

然后叫它:

bindMultiple($stmt, array(':fname', ':fname2'), $_POST['fname'], PDO::PARAM_STR);
Run Code Online (Sandbox Code Playgroud)

  • 我刚注意到一个问题.`bindParam`要求变量作为引用.我只是改变了`bindMultiple`来反映这一点. (2认同)

Lig*_*mer 18

下面的恕我直言,对于再次遇到这个问题的人来说,这是正确
注意:此语句假定user_id是表中的KEY.

陈述确实是错的,但接受的答案并不完全正确.

如果您使用相同的值插入和更新(并且不使用不同的值进行更新),则这是更正的查询伪代码:

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
}
Run Code Online (Sandbox Code Playgroud)

  • +1我同意当你需要使用参数时,使用`VALUES()`会更容易.但作为一个侧面问题,fwiw你不需要像在Java中那样在PHP中破坏你的字符串.您可以将多行字符串放入一组引号中. (5认同)