MySQL中NEW仅用于INSERT/UPDATE触发器,OLD仅用于UPDATE/DELETE触发器,DELETE中用NEW或INSERT中用OLD均报ERROR 1327;PostgreSQL需显式RETURN NEW;SQL Server用INSERTED/DELETED表而非变量。

MySQL 触发器里 NEW/OLD 变量在 INSERT/UPDATE/DELETE 中是否可用?
不可用就是硬性限制,不是“有时能用有时不能用”。NEW 在 INSERT 和 UPDATE 的触发器中有效,在 DELETE 中直接报错(ERROR 1327);OLD 只在 UPDATE 和 DELETE 中有效,在 INSERT 中访问会触发同样错误。常见误写是:IF NEW.status IS NULL THEN SET NEW.status = 'pending'; END IF; 放在 DELETE 触发器里——根本跑不起来。
实操建议:
- 写触发器前先确认事件类型,再决定用
NEW还是OLD,别靠记忆硬套 - 用
SHOW CREATE TRIGGER trigger_name;检查定义,重点看BEFORE/AFTER和INSERT/UPDATE/DELETE是否匹配变量使用 - 在测试阶段,对同一张表分别执行单条
INSERT、UPDATE、DELETE,观察是否全部成功,而不是只测一种
PostgreSQL 触发器函数里 NEW 是只读副本,赋值无效
PostgreSQL 不允许在触发器函数体中直接修改 NEW 字段并期望它影响插入结果——比如写 NEW.created_at := NOW(); 后没加 RETURN NEW;,或者写了但返回了别的东西,字段就不会被更新。这不是作用域问题,是语义约定:你必须显式 RETURN NEW;(BEFORE)或 RETURN NULL;(AFTER),否则行为未定义。
实操建议:
- 所有
BEFORE触发器函数末尾必须有RETURN NEW;或RETURN OLD;,漏写会导致字段值保持默认或NULL - 别在函数中间用
NEW.x := ...后又覆盖掉,例如NEW.x := 1; ... NEW := NULL;,这会让前面的赋值白做 - 用
RAISE NOTICE 'new.id=%', NEW.id;打印调试,比查日志表更快定位变量是否被正确读取和修改
SQL Server 触发器没有 NEW/OLD,靠 INSERTED/DELETED 表集合操作
SQL Server 根本不提供行级变量,INSERTED 和 DELETED 是临时表,不是变量。写成 IF @id = INSERTED.id 或 SELECT @val = name FROM INSERTED 是典型错误——当批量操作时,这些语句只取第一行,其余静默丢失。逻辑看似“判断了”,实际只生效于首行。
实操建议:
- 永远用集合式写法:
UPDATE t SET status = 'processed' FROM target_table t INNER JOIN INSERTED i ON t.id = i.id; - 校验类逻辑改用
NOT EXISTS (SELECT 1 FROM INSERTED i WHERE i.amount ,而不是 <code>IF (SELECT amount FROM INSERTED) - 测试必须用至少两行数据:
INSERT INTO orders VALUES (1,'a'),(2,'b');,否则根本暴露不了单值假设缺陷
跨数据库移植触发器时,变量引用语法不兼容
MySQL 允许 NEW.col 直接参与表达式,PostgreSQL 要求 NEW.col 出现在 RETURN 或 INSERT 目标列,SQL Server 则压根没这个语法。把 MySQL 触发器原样搬到 PostgreSQL,SET NEW.updated_at = NOW(); 会直接报错 “syntax error at or near SET”;挪到 SQL Server 更是连解析都过不去。
实操建议:
- 不要复制粘贴触发器代码跨库,先确认目标数据库方言:MySQL 8.0+、PostgreSQL 14、SQL Server 2019 对变量支持完全不同
- MySQL 中的
NEW赋值逻辑,在 PostgreSQL 中要写进函数体并显式RETURN NEW;;在 SQL Server 中得改成基于INSERTED表的UPDATE ... FROM - 用
DELIMITER $$(MySQL)、$$ LANGUAGE plpgsql(PG)、AS BEGIN ... END(SQL Server)严格区分语法块,避免因分号或换行导致截断
NULL、空字符串、超长值)组合验证,而不是只测单条成功语句。

















