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


11

我了解FOR EACH STATEMENT在执行时,表t上定义的触发器将运行一次UPDATE t ...

现在,当使用t定义时FOREIGN KEY ... REFERENCES a ... ON UPDATE CASCADE,我更新的N行a,这会导致触发器被调用一次或N次吗?

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


4
您可以创建一个测试用例!将其插入到触发器主体中的另一个表中,看看将获得多少行。然后用您自己的答案写下来(允许,甚至鼓励)!
Colin't Hart 2015年

2
前句提及FOR EACH STATEMENT与问题的其余部分正交。FK约束是通过特殊触发器实现的FOR EACH ROW
Erwin Brandstetter,2015年

1
@Erwin“每行一次”或“每行一次”?
ypercubeᵀᴹ

@ypercube:我添加了详细答案。
Erwin Brandstetter,2015年

Answers:


6

当前,外键约束是通过特殊的内部触发器实现的。他们都跑了FOR EACH ROW

请注意,这些是可以更改的实现细节,因此请不要依赖它。但是,在最近的几个主要版本中,基本内容并未更改,因此不太可能进行重大更改。

我使用一个简单的FK约束从tbl进行了快速测试tbltypeFOR EACH ROW在第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'

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

Postgres的2个字节tgtype smallint表示一个int16in C源代码,其中最低有效位进行编码TRIGGER_TYPE_ROW。详细说明在这里:

您可以使用一对相同的触发器轻松地对此进行测试,而只需更改FOR ROW/ STATEMENT...。


5

它确实执行了N次,最简单的方法是执行带有EXPLAIN ANALYZE前缀的语句,即

EXPLAIN ANALYZE UPDATE a SET col = 1 WHERE othercol = 'foo';

这将为您提供类似于以下信息:

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

(经过9.2测试)


1
这让我有些惊讶。在9.4上进行测试,结果相同。
dezso 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.