PostgreSQL 14 如何创建 SQL 触发器函数:返回规则、动态 SQL 与性能要点
时间:2026-08-24 | 作者:半糖攻略君 | 阅读:0在PostgreSQL 14中,触发器函数必须声明为RETURNS TRIGGER,且末尾需返回NEW/OLD/NULL,否则CREATE TRIGGER会直接报错。对于动态SQL,要使用format('%I', identifier)来安全拼接标识符,而访问NEW/OLD则需依据TG_OP分支进行判断。另外,行级触发器在批量操作时,性能开销会比较显著。
触发器函数必须返回 TRIGGER 类型
PostgreSQL 14 强制要求触发器函数声明 RETURNS TRIGGER,否则创建触发器时直接报错:ERROR: function must return type trigger。这不是警告,是硬性类型检查。
常见错误:写成 RETURNS void 或 RETURNS text,哪怕函数体里有 RETURN 语句也无效。
- 函数定义开头必须明确写
RETURNS TRIGGER(大小写不敏感,但推荐全大写) - 函数体末尾必须有
RETURN NEW、RETURN OLD或RETURN NULL,不能遗漏 RETURN NEW用于BEFORE INSERT/UPDATE,让修改后的行继续执行原操作RETURN NULL表示跳过当前行(常用于校验失败拦截)
动态 SQL 中拼接表名和字段名必须用 format('%I', ...)
在触发器函数里写 EXECUTE 'INSERT INTO ' || TG_TABLE_NAME || ' ...' 是危险且错误的——TG_TABLE_NAME 不是字符串变量,而是运行时值;直接拼接会引发 SQL 注入或解析错误。
正确做法是用 format() 配合占位符:
%I自动加双引号并转义,安全处理标识符(表名、列名、schema 名),例如format('SELECT %I FROM %I', 'name', TG_TABLE_NAME)%L处理字符串/数值字面量,等价于quote_literal(),自动处理NULL和单引号- 禁止混用:
EXECUTE format('... %I ...') USING ...中,USING只能传值,不能传标识符
NEW 和 OLD 字段访问必须按 TG_OP 分支判断
在 INSERT 触发器里读 OLD.id,或在 DELETE 里读 NEW.created_at,运行时报错:record "old" has no field "id"。PostgreSQL 14 不做静默兼容,而是严格按事件暴露记录变量。
实操建议:
- 用
TG_OP显式分支:IF TG_OP = 'UPDATE' THEN ... END IF; - 避免无条件引用:
OLD.updated_at只在UPDATE和DELETE中有效 - 需要统一取值时,可用
COALESCE(NEW.field, OLD.field),但要确认语义合理(比如审计时间字段)
FOR EACH ROW 触发器性能开销远超直觉
一条影响 50 万行的 UPDATE,FOR EACH ROW 触发器会被调用 50 万次。哪怕函数体只有一行赋值,开销也显著——尤其嵌套了 EXECUTE、JSON 构造或跨 schema 函数调用。
关键细节:
- 多个触发器共存时,执行顺序由创建时间决定(
pg_trigger.tgrelid + pg_trigger.tgname排序),无法靠BEFORE/AFTER控制依赖 - 若逻辑可批量处理(如日志归档),优先考虑
FOR EACH STATEMENT+ 手动查变更行,而非逐行触发 - 测试时别只用单行数据验证逻辑,务必在真实批量场景下压测
最容易被忽略的是:NEW 和 OLD 在语句级触发器中为 NULL,且 BEFORE 行级触发器中修改 NEW 后不 RETURN NEW,变更就完全丢失。
免责声明:文中图文均来自网络,如有侵权请联系删除,心愿游戏发布此文仅为传递信息,不代表心愿游戏认同其观点或证实其描述。
相关文章
更多-
- 迅捷路由器怎么调信号最强,设置时要注意什么?
- 时间:2026-08-27
-
- vivo浏览器怎么卸不掉?原因和解决方法在这里
- 时间:2026-08-27
-
- OPPO R11s黑屏了,怎么强制恢复出厂设置?
- 时间:2026-08-27
-
- 飞利浦显示器包装盒有生产日期和保修期吗?怎么看?
- 时间:2026-08-27
-
- 联想新平板开机必须联网吗?怎么做?
- 时间:2026-08-27
-
- 平板横竖屏切换设置与问题解决
- 时间:2026-08-27
-
- 移动电源容量怎么测?要准备哪些工具?
- 时间:2026-08-27
-
- 荣耀90 Pro防水吗?防水级别多少?怎么用才安全
- 时间:2026-08-27
精选合集
更多大家都在玩
大家都在看
更多-
- 糖尿病完全不能吃糖吗
- 时间:2026-09-15
-
- 蚂蚁庄园小课堂2026年9月16日最新题目答案
- 时间:2026-09-15
-
- 小鸡答题今天的答案是什么2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园每日答题答案2026年9月16日
- 时间:2026-09-15
-
- 以下哪种粮食是酿造绍兴黄酒的主要原料 蚂蚁庄园今日答案9月16日
- 时间:2026-09-15
-
- 劝学名句“及时当勉励,岁月不待人”出自哪位诗人 蚂蚁庄园今日答案9.16
- 时间:2026-09-15
-
- 蚂蚁庄园今天答题答案2026年9月16日
- 时间:2026-09-15
-
- 蚂蚁庄园答题今日答案2026年9月16日
- 时间:2026-09-15
