校验逻辑必须放在 BEFORE INSERT 或 BEFORE UPDATE 中AFTER 仅适用于日志记录等不干预主流程的操作因数据已落库校验失效且无法阻止脏数据短暂可见。触发器里用 AFTER INSERT 还是 BEFORE INSERT校验逻辑必须放在 BEFORE INSERT 或 BEFORE UPDATE 里。如果写成 AFTER数据已经落库再抛错只会回滚事务但无法阻止脏数据短暂存在——尤其在高并发下可能被其他会话读到即使隔离级别高AFTER 的校验也失去意义。BEFORE 触发器中可直接修改 NEW 字段比如标准化手机号、补默认值也能用 SIGNAL SQLSTATE 45000 主动报错中断插入AFTER 只适合做日志记录、异步通知等不干预主流程的操作不能用于完整性兜底MySQL 8.0 支持 BEFORE DELETE 做级联校验比如检查子表是否为空但老版本只能靠应用层或外键约束SIGNAL SQLSTATE 报错时为什么总提示 Unknown errorMySQL 对 SIGNAL 的错误信息长度有限制最大64字符且不支持变量拼接。直接写 SIGNAL SQLSTATE 45000 SET MESSAGE_TEXT CONCAT(金额不能为负:, NEW.amount) 会静默失败最终只报泛泛的 Unknown error。必须用字面量字符串SIGNAL SQLSTATE 45000 SET MESSAGE_TEXT 金额不能为负;如需动态内容先用 IF 判断再分路 SIGNAL例如IF NEW.amount 避免在触发器里调用存储函数返回错误信息——函数执行失败会导致整个触发器中断且错误不可控触发器访问其他表导致性能崩了怎么办在 BEFORE INSERT 里写 SELECT ... FROM orders WHERE user_id NEW.user_id 是典型陷阱每插一条就查一次批量导入时变成 N1 查询锁表风险陡增。 有道翻译AI助手 有道翻译提供即时免费的中文、英语、日语、韩语、法语、德语、俄语、西班牙语、葡萄牙语、越南语、印尼语、意大利语、荷兰语、泰语全文翻译、网页翻译、文档翻译、PDF翻