【问题标题】:Only update changed values for ON DUPLICATE KEY UPDATE仅更新 ON DUPLICATE KEY UPDATE 的更改值
【发布时间】:2014-06-23 16:41:28
【问题描述】:

我有一个复选框列表,这些复选框被赋值为 1 或 0,它们都被传递到 $_POST 变量中。

我当前的 sql 语句正确插入了所有这些,但是当我更改值并再次运行 sql 语句时,它会更新所有项目的“updated_at”列。

有没有办法只更新更改的值,这样它就不会更新每个条目的“updated_at”列? id 是我的主键,site_id 是唯一的。

SQL 语句:

        $sql = "INSERT INTO admin_sites2 (site_id,created_at,active)
                VALUES ('$key',now(),'$value')
                ON DUPLICATE KEY
                UPDATE active = $value,
                updated_at = now()
               ";

【问题讨论】:

  • id 必须是查询的一部分。但你没有。我假设只是一个小小的疏忽。修复它,你应该会没事的。
  • @hakre:我不确定我是否理解您的评论。看起来site_id 是该表上的唯一键;必须至少有一个唯一约束才能引发“重复键”异常;而且我们不想更新那个唯一键的值。
  • @spencer7593:我假设主键 - 不是唯一键 - 需要 INSERT INTO ... ON DUPLICATE KEY UPDATE 工作。我可能错了,但我可以想象这是问题的一部分,并且可以作为快速解决方案。
  • @hakre:可以为任何唯一约束引发“重复键”异常,无论是主键还是唯一键。 (一个表可以有多个唯一约束;在“重复键”异常中标识的任何一个键都是 UPDATE 操作用来标识行的键值。

标签: php mysql sql-update insert-update


【解决方案1】:

我建议您使用特殊的 VALUES() 函数来引用本应插入列中的值(如果插入成功)。

您可以使用将列的当前值与新提供的值进行比较的表达式,并有条件地返回列的当前值或新的表达式。

例如:

            INSERT INTO admin_sites2 (site_id,created_at,active)
            VALUES ('$key',now(),'$value')
            ON DUPLICATE KEY
            UPDATE updated_at = IF(active=VALUES(active),updated_at,NOW()),
            active = VALUES(active)

表达式 IF(a,b,c) 的工作方式如下:它将a 计算为布尔值;如果a 为真则返回b 否则返回c

在上面的示例中,如果active 列的当前值与插入/分配的新值相同,则IF() 表达式返回updated_at 列的当前值。 (这意味着updated_at 列的值不会改变,因为它分配了已经存储的值。)否则,NOW() 的值将分配给updated_at 列。

我认为在分配给active 列之前检查active 列的当前值很重要。 (请注意,updated_at 的分配出现在 active 的分配之前。)

这是因为 MySQL 在 SQL 中处理值的方式。 MySQL 不维护行的一致快照视图(“在语句的开头”)。为列分配新值后,以后对该列的引用将返回新分配的值,而不是语句开始更改行之前的值。

【讨论】:

  • 完美,这正是我想要的。谢谢!
  • 当有 50 个非关键列要比较时,是否有技巧/替代方法? IE。不仅仅是这个例子中的活动列,而是说我们需要检查更新的 50 列,然后再决定保持相同的 updated_at
【解决方案2】:

虽然我确信这可以在单个查询中完成,但您为什么不直接进行多个查询呢?只需选择active 列,其中site_id 等于$key。如果没有结果,请插入并设置updated_at。如果存在且值不同,请更新两列。否则什么都不做

【讨论】:

  • 不这样做有几个原因。这种方法使往返数据库的往返次数增加了一倍,语句解析、锁定等方面的开销更大,这在轻负载系统上可能不是性能问题,但确实会影响可伸缩性。这种方法也有可能出现竞争条件。在两个语句(SELECT 和 UPDATE)之间有一小段时间,供另一个会话修改(或删除)该行。在这个特定的用例中可能不是一个问题,但在更一般的情况下是一个考虑因素。
猜你喜欢
  • 2018-01-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-10
  • 2016-08-28
  • 1970-01-01
相关资源
最近更新 更多