首页 > 解决方案 > 将 MySQL 语法用于 INSERT INTO SET 和 ON DUPLICATE KEY UPDATE (具有相同的列集)是否可能且安全?

问题描述

我知道特定的 MySQL 查询语法是如何工作INSERT INTO SETON DUPLICATE KEY UPDATE。但是,你能把它们结合起来吗?并且...您可以对和部分使用相同的$columnSet字符串(见下文),将唯一字段留在其中吗?INSERTUPDATE

考虑这个例子(我在我的服务器上使用 php 和 pdo):

// Define the query
$columnSet = "id=:id, date=:date, created=:created, modified=:modified, removed=:removed, synced=1, points=:points, comment=:comment";
$insertQuery = "INSERT INTO point_events SET"
               . $columnSet." ON DUPLICATE KEY UPDATE ".$columnSet;

   // Define the data
    $pointData['id'] = 'someuniqueid not auto incremented';
$pointData['created'] = 1234; // a timestamp
$pointData['modified'] = 1234; // a timestamp
$pointData['removed'] = NULL;
$pointData['points'] = 10;
$pointData['comment'] = "A comment";
$pointData['date'] = time();

// Execute the query. pdoModify is custom function that executes the query.
pdoModify($pdoNew, $insertQuery, $oldData); 

我看到的所有帖子都没有结合这两种语法,并且所有帖子ON DUPLICATE KEY UPDATE似乎都建议您不应该在UPDATE. 那么,这是否安全,或者这是否会表现不同/有不必要的副作用。特别是在 $columnSet 中为 UPDATE 保留唯一 ID 是我所关心的。

标签: phpmysqlpdo

解决方案


我相信您的代码应该可以工作。通常,由于id最初检查重复的唯一键,因此可以保证在ON DUPLICATE KEY调用子句时它不会保持不变。

但是,这种行为是次优的(您正在更新未更改的字段),并且非常严格:如果您需要增加新插入的值,或者在现有值的末尾amount连接新值怎么办?comment

正如Rogue所评论的,MySQL 语法有一个很好的特性,它允许VALUES(<some column>)ON DUPLICATE KEY子句中使用 to 来引用传递给的值INSERT。我建议使用它,因为它更优雅,并且给你更多的控制和灵活性。

例子:

$insertQuery = 
    "INSERT INTO point_events SET"
    . $columnSet
    ." ON DUPLICATE KEY UPDATE"
    ." modified =  VALUES(modified)"                  # replace this value
    .", synced = 1"                                  # assign a fixed value
    .", amount = amount + VALUES(amount)"             # add the new value
    .", comment = CONCAT(comment, ', ', VALUES(comment))"    # concatenante the new value

推荐阅读