在 Postgres 9.0 或更高版本中,在触发器定义(语句)中添加一个WHEN
子句:CREATE TRIGGER
CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD IS DISTINCT FROM NEW) -- parentheses required!
EXECUTE PROCEDURE ...;
仅适用于触发器BEFORE
/ AFTER
UPDATE
,其中定义了OLD
和。NEW
尝试将此WHEN
子句与INSERT
orDELETE
触发器一起使用时,您会遇到异常。
并相应地从根本上简化触发功能:
...
IF OLD.locked > 0 THEN
RAISE EXCEPTION 'Message';
END IF;
...
无需测试IF TG_OP='UPDATE' ...
,因为此触发器仅适用于任何情况UPDATE
。
或者将该条件也移到 WHEN 子句中:
CREATE TRIGGER foo
BEFORE UPDATE
FOR EACH ROW
WHEN (OLD.locked > 0
AND OLD IS DISTINCT FROM NEW)
EXECUTE PROCEDURE ...;
在您的触发函数中只保留一个无条件RAISE EXCEPTION
,仅在需要开始时调用。
阅读细则:
在BEFORE
触发器中,WHEN
条件在函数正在执行或将要执行之前被评估,因此使用WHEN
与在触发器函数开始时测试相同条件没有本质区别。请特别注意,NEW
条件看到的行是当前值,可能已被早期触发器修改。此外,BEFORE
触发器的WHEN
条件不允许检查行的系统列NEW
(例如oid
),因为尚未设置这些列。
在AFTER
触发器中,WHEN
在行更新发生后立即评估条件,并确定事件是否排队以在语句结束时触发触发器。因此,当AFTER
触发器的
WHEN
条件未返回 true 时,无需将事件排队,也无需在语句末尾重新获取行。如果只需要为少数几行触发触发器,这可能会导致修改多行的语句显着加速。
有关的:
还要解决问题标题
是否可以动态循环遍历表的列?
是的。例子: