仅在真正更改数据的情况下,才有可能使用“更新后”触发器。我知道“新旧”。但是使用它们时,我只能比较列。例如“ NEW.count <> OLD.count”。
但我想要类似的东西:如果“ NEW <> OLD”,则运行触发器
一个例子:
create table foo (a INT, b INT); create table bar (a INT, b INT);
INSERT INTO foo VALUES(1,1); INSERT INTO foo VALUES(2,2); INSERT INTO foo VALUES(3,3);
CREATE TRIGGER ins_sum AFTER UPDATE ON foo FOR EACH ROW INSERT INTO bar VALUES(NEW.a, NEW.b);
UPDATE foo SET b = 3 WHERE a=3; Query OK, 0 rows affected (0.00 sec) Rows matched: 1 Changed: 0 Warnings: 0
select * from bar; +------+------+ | a | b | +------+------+ | 3 | 3 | +------+------+ 关键是,有一个更新,但是什么都没有改变。但是无论如何,触发器都在运行。恕我直言,应该有一个没有的方法。
我知道我可以使用
如果现在b <> OLD.b
对于这个例子。
但是,想象一下一个带有变化列的大桌子。您必须比较每列,如果数据库发生更改,则必须调整触发器。并且比较硬编码的行的每一列都是“感觉”不好:)
加成
如您所见
匹配的行:1已更改:0警告:0
MySQL知道这条线没有改变。但是它不会与触发器共享这些知识。像“ AFTER REAL UPDATE”之类的触发器或类似的东西会很酷。
作为一种解决方法,您可以使用时间戳(旧的和新的)来检查,如果该行没有更改,则不会更新该时间戳。(可能是造成混乱的根源?因为那也被称为“更新时”,但是在没有任何变化的情况下不会执行)一秒钟之内的变化将不会执行触发器的那部分,但是在某些情况下可能会很好(例如,当您的应用程序仍然拒绝快速更改时。)
例如,而不是
IF NEW.a <> OLD.a or NEW.b <> OLD.b /* etc, all the way to NEW.z <> OLD.z */ THEN
INSERT INTO bar (a, b) VALUES(NEW.a, NEW.b) ; END IF 你可以用
IF NEW.ts <> OLD.ts THEN
INSERT INTO bar (a, b) VALUES(NEW.a, NEW.b) ; END IF 这样,您就不必在每次更新方案时都更改触发器(问题中提到的问题)。
编辑:添加了完整的示例
create table foo (a INT, b INT, ts TIMESTAMP); create table bar (a INT, b INT);
INSERT INTO foo (a,b) VALUES(1,1); INSERT INTO foo (a,b) VALUES(2,2); INSERT INTO foo (a,b) VALUES(3,3);
DELIMITER ///
CREATE TRIGGER ins_sum AFTER UPDATE ON foo FOR EACH ROW BEGIN IF NEW.ts <> OLD.ts THEN
INSERT INTO bar (a, b) VALUES(NEW.a, NEW.b); END IF; END; ///
DELIMITER ;
select * from foo; +------+------+---------------------+ | a | b | ts | +------+------+---------------------+ | 1 | 1 | 2011-06-14 09:29:46 | | 2 | 2 | 2011-06-14 09:29:46 | | 3 | 3 | 2011-06-14 09:29:46 | +------+------+---------------------+ 3 rows in set (0.00 sec)
-- UPDATE without change UPDATE foo SET b = 3 WHERE a = 3; Query OK, 0 rows affected (0.00 sec) Rows matched: 1 Changed: 0 Warnings: 0
-- the timestamo didnt change select * from foo WHERE a = 3; +------+------+---------------------+ | a | b | ts | +------+------+---------------------+ | 3 | 3 | 2011-06-14 09:29:46 | +------+------+---------------------+ 1 rows in set (0.00 sec)
-- the trigger didn't run select * from bar; Empty set (0.00 sec)
-- UPDATE with change UPDATE foo SET b = 4 WHERE a=3; Query OK, 1 row affected (0.00 sec) Rows matched: 1 Changed: 1 Warnings: 0
-- the timestamp changed select * from foo; +------+------+---------------------+ | a | b | ts | +------+------+---------------------+ | 1 | 1 | 2011-06-14 09:29:46 | | 2 | 2 | 2011-06-14 09:29:46 | | 3 | 4 | 2011-06-14 09:34:59 | +------+------+---------------------+ 3 rows in set (0.00 sec)
-- and the trigger ran select * from bar; +------+------+---------------------+ | a | b | ts | +------+------+---------------------+ | 3 | 4 | 2011-06-14 09:34:59 | +------+------+---------------------+ 1 row in set (0.00 sec) 由于mysql在处理时间戳方面的行为,因此可以正常工作。仅当更新中发生更改时,时间戳才会更新。
文档在这里:https : //dev.mysql.com/doc/refman/5.7/en/timestamp-initialization.html来源:stack overflow
版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。