return new表示用修改后的数据继续执行insert/update,return null则跳过当前行且后续触发器不再执行;语句级触发器必须显式return null,否则报错。

RETURN NEW 和 RETURN NULL 的区别在哪
行级 BEFORE 触发器中,返回值直接决定语句是否继续执行:RETURN NEW 表示用修改后的数据继续插入或更新;RETURN NULL 表示跳过当前行(整行操作被丢弃),后续触发器也不再执行。常见错误是漏写 RETURN 语句——PL/pgSQL 中函数末尾无显式返回时默认为 NULL,但这个隐式行为极易被误认为“没生效”,实际已静默丢弃数据。
语句级触发器必须写 RETURN NULL
语句级触发器(FOR EACH STATEMENT)不访问 OLD/NEW,只做全局动作(如日志计数、权限检查)。它的函数体里**必须显式写 RETURN NULL**,否则会报错:ERROR: control reached end of trigger procedure without returning a value。这不是风格问题,是语法强制要求——和行级触发器的语义完全不同。
UPDATE/INSERT 触发器中修改 NEW 并返回的典型场景
当需要在写入前标准化字段时,比如自动补全空字符串、转小写、生成 UUID,就得在函数里改 NEW 字段再 RETURN NEW:
IF NEW.email IS NOT NULL THEN NEW.email := lower(trim(NEW.email)); END IF; RETURN NEW;
注意三点:
• 必须用 BEFORE 触发时机,AFTER 中 NEW 已不可变
• 修改的是 NEW 记录本身,不是原表字段
• 如果判断条件不满足,仍需兜底 RETURN NEW,否则该行会被丢弃
容易被忽略的 TRUNCATE 和 INSTEAD OF 场景
TRUNCATE 只支持语句级 BEFORE/AFTER 触发器,且只能定义在普通表上;它的触发器函数也必须 RETURN NULL。INSTEAD OF 触发器仅用于视图,返回值逻辑类似行级 BEFORE:返回 NULL 表示取消操作,返回 NEW 或 OLD(取决于操作类型)表示替代执行。这类触发器一旦启用,原 INSERT/UPDATE/DELETE 就完全不会触发表本身,所以返回值控制权更重——稍有不慎就导致数据不写入。











