MySQL触发器问题:仅在更改列时触发?

25

我不知道这是否可行,但我在一个表中有一个名为active的列。每当更改active列时,我想重设date列中的日期,但仅当更改了active列时。

如果更改其他列而不是active列,则日期将保持不变。


在更新之前需要检查活动列的旧值和新值,参见http://www.java2s.com/Code/Oracle/Trigger/ReferenceoldandnewvaluebycolumninabeforeupdateTrigger.htm中的示例。 - Haim Evgi
https://dev59.com/Bm015IYBdhLWcg3w9gjh - zloctb
2个回答

41

类似于什么东西

DELIMITER //
 CREATE TRIGGER updtrigger BEFORE UPDATE ON mytable
     FOR EACH ROW
     BEGIN
     IF NEW.active <> OLD.active THEN
     SET NEW.date = '';     
     END IF;
     END
     //

如果我想将日期更新为当前日期,那么这行代码会变成 SET NEW.date = CURDATE(); 吗? - kylex
4
如果您想要日期,使用“yes”,如果您想要日期和时间,请使用NOW()。 - Haim Evgi
1
如果在数据库中active已经是1的情况下,你设置了active = 1,那么这不就是一次更改吗?从技术上讲,是的,因为你已经设置了该列,在数据库术语中这是一次列更改。但是NEW.active不等于OLD.active只有在NEW和OLD具有不同的值时才成立!那么在这种情况下你会怎么做呢?@HaimEvgi - edam
1
使用 <=> 代替 <> 不是更好吗? - stack
2
@stack 是的,尽管不是字面上的意思,<=> 表示“相等”,其中 null 被视为可比较的值。 因此,您需要更改为 not NEW.active <=> OLD.active - Brian Leishman

19

在第2个示例中,我遇到了IF测试的问题。当其中一个值为null时,<>测试会返回null。这导致测试未被满足,即使一个值根本不等于null,触发器的操作也不会被运行。为了解决这个问题,我想出了使用<=>(NULL安全相等)的测试。希望这能帮助某些人。

DELIMITER $$
DROP TRIGGER IF EXISTS updtrigger ;
$$
CREATE TRIGGER updtrigger  AFTER UPDATE
    ON yourTable FOR EACH ROW
BEGIN
    IF ((NEW.active <=> OLD.active) = 0)  THEN
     SET NEW.date = '';     
     END IF;
$$

5
你可以简单地使用 NOT 运算符代替与零的比较,就像这个答案中所示:https://dev59.com/rGzXa4cB1Zd3GeqPRTvH#24041832。否则,回答不错。 - user2428118
1
最后的$$之前不应该加上END吗? - Ricky McMaster
@Johnglassman - 为什么不使用BEFORE而不是AFTER? - Valter Ekholm
@ValterEkholm 这是很久以前的事情了,但我怀疑我的用例是一个触发器之后,并且这不是我帖子中相关的方面。我敢打赌测试无论触发操作如何都会表现出相同的行为。 - John Glassman
@JohnGlassman 好的,看来多年过去了你还记得很清楚。我记得当时测试了“after”,但它没有起作用,所以我发表了这个/那个评论,但是在使用“before”时(据我记得)它确实起作用了。谢谢。 - Valter Ekholm

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接