单靠update('col')不行,因其仅检测字段是否出现在set子句中,不判断值是否变化;必须配合not (old.col new.col)确认真实变更,且需处理null安全比较与字符串敏感性。

必须同时用 UPDATE() 检查字段是否出现在 SET 子句中,再用 OLD.col NEW.col 确认值确实变了——缺一不可。
为什么单靠 UPDATE('col') 不行
UPDATE('col') 只检测 SQL 语句里有没有写这个字段,不关心值变没变。比如 UPDATE users SET email = OLD.email,哪怕 email 根本没改,UPDATE('email') 也返回 TRUE。
- INSERT/DELETE 触发器里调用会直接报错:
FUNCTION db.UPDATE does not exist - 不能传多个字段:
UPDATE('a','b')或UPDATE(['a','b'])是语法错误 - 它只是个“字段是否被提及”的开关,不是“值是否变更”的判断器
为什么必须用 而不是 !=
NULL != NULL 返回 NULL(逻辑上为 false),导致条件失效。比如旧值是 NULL、新值是 'abc',OLD.email != NEW.email 仍可能不成立。
MySQL 9.6.0是面向Linux平台的2026年创新版本,核心架构迎来重大革新。其将外键约束与级联操作从InnoDB引擎层上移至SQL层,确保所有数据变更均被完整记录至Binlog,彻底解决了CDC(变更数据捕获)与主从复制中的数据不一致难题。此外,该版本引入container_aware启动选项以原生适配容器环境,并对审计日志进行了组件化重构,为追求极致数据一致性与云原生体验的开发者提供了全新选择。
-
是 MySQL 的空安全等于:两边都为NULL时返回TRUE,一空一非空时返回FALSE - 真要检测“变化”,得写
NOT (OLD.col NEW.col),等价于“值不同” - 字符串字段若涉及大小写或尾部空格敏感,可加
BINARY:NOT (BINARY OLD.name BINARY NEW.name)
多个字段必须同时更新才触发怎么办
比如业务要求:只有 status 和 updated_at 都出现在 UPDATE 语句中,且值都变了,才写日志。
- 先确保都在 SET 里:
UPDATE('status') AND UPDATE('updated_at') - 再确认值真变了:
NOT (OLD.status NEW.status) AND NOT (OLD.updated_at NEW.updated_at) - 两个条件必须 AND 连接,缺一个都不进逻辑块
- 别在触发器顶层无条件执行
SET NEW.updated_at = NOW(),否则每次 UPDATE 都覆盖时间戳
容易被忽略的性能与递归风险
触发器里嵌套 SELECT 或 UPDATE 其他表时,容易拖慢主更新,甚至引发死锁或递归触发(比如更新日志表又触发另一个触发器)。
- 避免在 IF 块里写
SELECT COUNT(*) FROM ...这类聚合查询 - 如果逻辑涉及多表更新,优先考虑应用层处理,或用异步队列替代
-
AFTER UPDATE中修改本表会报错;BEFORE UPDATE修改NEW是安全的,但别误改不该动的字段










