old仅在update和delete触发器中可用,insert触发器中引用old会直接报错;before/after update和delete均可读old但不可写,insert任何时机均不可用old。

INSERT触发器里访问OLD会直接报错
因为INSERT操作没有“修改前的状态”,OLD根本不存在。MySQL在解析触发器时就检查上下文,一旦发现OLD.id这类引用出现在INSERT触发器中,立刻抛出ERROR 1363 (HY000): There is no OLD row in on INSERT trigger,不等执行。
哪些操作能用OLD,哪些不能
OLD只在UPDATE和DELETE触发器中可用,且仅限于这两个事件类型:
-
BEFORE UPDATE:可读OLD.col,不可写 -
AFTER UPDATE:可读OLD.col,不可写 -
BEFORE DELETE:可读OLD.col,不可写 -
AFTER DELETE:可读OLD.col,不可写 -
INSERT(任何时机):OLD完全不可用,引用即语法错误
容易误判的典型场景
常见错误不是手误,而是逻辑混淆:
- 把
BEFORE INSERT当成“可以读旧值”的入口,试图用OLD做默认值兜底——其实该用NEW.col IS NULL判断是否为空再赋值 - 复制了
UPDATE触发器代码到INSERT中,忘了删掉所有OLD.前缀 - 在存储过程里封装了通用字段处理逻辑,传入
OLD参数,但调用方是INSERT触发器——OLD无法作为变量传入,作用域不匹配
真正该关注的边界点
最常被忽略的是:报错发生在**解析阶段**,不是运行时。这意味着即使OLD出现在IF FALSE THEN ... END IF块里,只要语法树里存在,就会失败。MySQL不搞“懒解析”。











