避免MySQL触发器在未修改行上执行
MySQL触发器在表上发生特定操作(如插入、更新或删除)时执行。但是,默认情况下,“after update”触发器即使没有对表行进行任何更改也会激活。
为什么“After Update”触发器即使没有更改也会执行?
检测更新行中更改的常规方法是比较行的“新”版本和“旧”版本之间的各个列值。但是,随着表中列数的增加,这种方法变得繁琐且容易出错。
解决方案:利用行时间戳来确定更改
解决此问题的一个巧妙方法是使用行时间戳列。MySQL为每一行维护两列时间戳:创建时间戳和更新时间戳。每当插入或更新一行时,这些时间戳都会自动更新。
基于时间戳比较的触发器执行
通过比较新的和旧的时间戳,我们可以确定是否对行进行了更改。以下触发器代码说明了这种方法:
<code class="language-sql">CREATE TRIGGER ins_sum AFTER UPDATE ON foo FOR EACH ROW BEGIN IF NEW.ts <> OLD.ts THEN -- 已进行更改;执行触发器主体 END IF; END;</code>
在此触发器中,“NEW.ts”和“OLD.ts”分别表示新的和旧的时间戳值。如果值不同,则表示发生了更改,并且执行触发器主体。
示例
考虑以下示例:
<code class="language-sql">CREATE TABLE foo (a INT, b INT, ts TIMESTAMP); -- 插入一些行 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 ; -- 不更改地更新 UPDATE foo SET b = 3 WHERE a = 3; -- 更改地更新 UPDATE foo SET b = 4 WHERE a = 3;</code>
执行第一次更新(不进行任何更改)后,触发器不会运行。但是,第二次更新会更改该行,并且会执行触发器,从而将新行插入到“bar”表中。
此解决方案无需显式比较各个列值,并确保仅在对行进行实际更改时才执行触发器。
以上是如何防止 MySQL'更新后”触发器在未更改的行上触发?的详细内容。更多信息请关注PHP中文网其他相关文章!