如果操作是由带有 UPDATE CASCADE 的 FK 约束引起的,那么 FOR EACH STATEMENT 触发器多久执行一次?

Han*_*etz 12 postgresql trigger foreign-key postgresql-9.2

我知道FOR EACH STATEMENT当我执行一个UPDATE t ....

现在,什么时候用t定义FOREIGN KEY ... REFERENCES a ... ON UPDATE CASCADE,我更新 N 行a,这会导致触发器被调用一次还是 N 次?

换句话说,对由 FK 约束级联的表的更改更像是单个UPDATE,还是更像是一系列UPDATEs?

Erw*_*ter 7

外键约束目前使用特殊的内部触发器实现。他们都跑了FOR EACH ROW

请注意,这些是可以更改的实现细节,所以不要依赖它。但是在过去的几个主要版本中基本没有改变,因此不太可能发生重大变化。

我用一个简单的 FK 约束从tblto运行了一个快速测试tbltypeFOR EACH ROW在我对 pg 9.4 的测试中,使用四个简单的内部触发器实现了一个简单的 FK 。
以下是有关如何调查的简要概述:

SELECT oid  -- 74791
FROM   pg_constraint
WHERE  conrelid = 'tbl'::regclass
AND    contype = 'f';

SELECT objid, classid::regclass  -- 74792,74793,74794,74795 / 'pg_trigger'
FROM   pg_depend
WHERE  refobjid = 74791
AND   deptype = 'i'

SELECT tgrelid::regclass, tgname, tgfoid, tgtype FROM pg_trigger
WHERE  oid IN (74792,74793,74794,74795) ORDER BY tgfoid;

'tbl'    ;'RI_ConstraintTrigger_c_74794';1644;5
'tbl'    ;'RI_ConstraintTrigger_c_74795';1645;17
'tbltype';'RI_ConstraintTrigger_a_74792';1654;9
'tbltype';'RI_ConstraintTrigger_a_74793';1655;17

SELECT oid, proname FROM pg_proc
WHERE oid IN (1654,1655,1644,1645);

1644;'RI_FKey_check_ins'
1645;'RI_FKey_check_upd'
1654;'RI_FKey_noaction_del'
1655;'RI_FKey_noaction_upd'
Run Code Online (Sandbox Code Playgroud)

两个内部“noaction”触发tbltype
上的两个内部“检查”触发器tbl
所有这些都运行FOR EACH ROW,如 中的奇数所示tgtype

Postgres 的 2 个字节tgtype smallint表示int16C 源代码中的最低有效位编码TRIGGER_TYPE_ROW。详细解释在这里:

您可以使用一对相同的触发器轻松测试这一点,您只需更改FOR ROW/ STATEMENT...


Han*_*etz 6

它确实执行了 N 次,看到这一点的最简单方法是执行带有EXPLAIN ANALYZE前置的语句,即

EXPLAIN ANALYZE UPDATE a SET col = 1 WHERE othercol = 'foo';
Run Code Online (Sandbox Code Playgroud)

这将为您提供与此类似的信息:

Trigger for constraint t_col_fk on a: time=1.300 calls=9

(用 9.2 测试)