【问题标题】:Conditional on duplicate key update not working correctly以重复密钥更新无法正常工作为条件
【发布时间】:2016-06-05 07:51:32
【问题描述】:

只有当 is_active 字段的旧值为 0 且更改为 1 时,我才需要将我的 created_on 日期时间字段值更新为 NOW()

+-----------+---------+-----------+---------------------+---------------------+
| device_id | user_id | is_active | created_on          | last_modified_on    |
+-----------+---------+-----------+---------------------+---------------------+
|         5 |       5 |         0 | 2016-06-05 03:31:48 | 2016-06-05 03:31:48 | 

这是我目前所得到的:

INSERT INTO `device2users` 
(`device_id`, `user_id`, `is_active`, `created_on`, `last_modified_on`) 
VALUES 
(5, 5, 1, NOW(), NOW()) 
ON DUPLICATE KEY UPDATE 
`created_on` = CASE WHEN `is_active` <> 0 THEN VALUES(`created_on`) ELSE NOW() END, 
`is_active`=1, `last_modified_on`=NOW();

但它不起作用,created_on 字段的值始终设置为NOW()

编辑 1:

我想将 created_on 字段的值更新为 NOW() ON DUPLICATE KEY,前提是 is_active 字段的值之前为 0 并且在指定查询中为 1

编辑 2:

我根据@ring Bearer 的回答使用以下查询。但我明白了:

ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '== '0' && NEW.is_active == '1' THEN

这是我正在使用的确切查询。

DELIMITER //

CREATE TRIGGER created_on_after_update
        AFTER UPDATE
        ON `acd_device2users` FOR EACH ROW

BEGIN
        IF OLD.is_active == '0' && NEW.is_active == '1' THEN
            SET `created_on`=NOW();
        END IF;
END; //

DELIMITER ;

【问题讨论】:

  • 你到底想达到什么目的?您提供的数据不符合此条件。
  • created_on 的值将根据您编写的代码设置为 NOW()。当您的语句执行时,is_active 的值为 0。在您的案例陈述中,您是说当is_active 为0 时,created_on 应更新为NOw()

标签: mysql conditional on-duplicate-key


【解决方案1】:

您只需要created_on,而您拥有values(created_on)。 values 返回如果没有重复键(在您的情况下是 now() ),则该列将设置为的值,而不是旧值。

如果您在设置之前使用它们,更新部分中的列名将返回它们的旧值。因此,如果 is_active 从 0 变为 1,则仅更改 created_on,请执行以下操作:

ON DUPLICATE KEY UPDATE
    created_on = CASE WHEN is_active=0 && VALUES(is_active)=1 THEN VALUES(created_on) ELSE created_on END,
    is_active = VALUES(is_active),
    last_modified_on = VALUES(last_modified_on);

使用 VALUES 而不是硬编码的 1 或 NOW() 可以正确使用在创建新行时会使用的任何值。

【讨论】:

  • 我不知道@ysth。谢谢。但我认为这需要使用触发器来完成,就像 ring Bearer 在他的回答中描述的那样,因为我需要知道 is_active 的先前值。我已经为你投票了,它会在我有 15 次代表时显示。
  • 啊,我没有注意到你问题的那一部分。您不需要使用触发器;我会更新我的答案
【解决方案2】:

我建议使用更新触发器来使其正常工作。在该触发器中,您将跟踪对is_active 字段的更改并将必填字段设置为必填值。示例:

DELIMITER //

CREATE TRIGGER created_on_after_update
BEFORE INSERT
   ON my_table FOR EACH ROW

BEGIN
       IF (NEW.is_active = '1') THEN
         //Set required change.
       END IF;
END; //

DELIMITER ;

在插入过程中,您只需检查 NEW.is_active 并做出如上所示的决定。

【讨论】:

  • 谢谢。我是触发器的新手。我刚刚尝试了您的解决方案,但在near '== '0' &amp;&amp; NEW.is_active == '1' THEN 附近出现语法错误ERROR 1064 (42000):。我正在编辑我的问题以添加我正在使用的确切查询。请你看一下。
  • 很抱歉,由于我的声誉不佳,我无法投票给你。 :(
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-24
  • 2023-04-07
  • 2017-08-14
相关资源
最近更新 更多