我想知道在PostgreSQL(9.3)中有关于孙子表的UPDATE CASCADE的FK触发器的执行/触发顺序
这就是我所拥有的:
Parent: Invoices (invoice_id)
Child: Invoice_Lines (invoice_id, line_nbr)
Grandchild: Invoice_Line_Taxes (invoice_id, line_nbr, tax)
Invoice_Lines has FOREIGN KEY (invoice_id) REFERENCES Invoices ON UPDATE CASCADE;
Invoice_Line_Taxes has FOREIGN KEY (invoice_id, line_nbr) REFERENCES Invoice_Lines ON UPDATE CASCADE;
我还在发票上有一个自定义UPDATE触发器(谁的名字以S开头,后面是RI_)。此触发器总结了发票金额。我的实际更新语句更改了invoice_id,它会传播到子孙。
麻烦的是,在我的自定义触发器中/期间,Invoice_Lines的invoice_id已经更改,但不是孙子Invoice_Line_Taxes。
我使用RAISE从自定义触发器中转储行:
invoice_lines: (5,1)
invoice_line_taxes: (-1,1,HST)
触发后:
SELECT * from invoice_line_taxes where invoice_id IN (5,-1);
invoice_id | line_nbr | tax_nm
------------+----------+--------
5 | 1 | HST
所以我想知道,关于级联触发器的触发器执行顺序是什么?
我会假设这样的事情:
RI_on_invoices
RI_on_invoice_lines
S_custom_trigger
有什么想法吗?有人知道在哪里可以得到关于执行顺序的官方文档吗?我已经尝试过查找有关此内容的详细文档,但我发现所有内容都是按字母顺序排列的。也许如果我找到有关订购的具体细节,我可以在它周围建立一些东西。但是现在,我将基于猜测工作。
谢谢。
答案 0 :(得分:2)
触发器执行顺序确实是按字母顺序排列的,您希望在此处将其理解为ASCII字符串顺序"0" < "A" < "_" < "a"
,同时请记住"A3" < "a1" < "a10" < "a2"
。
如果要以特定顺序强制执行,则可以更简单地为触发器名称添加前缀,例如(注意标识符以数字开头时的双引号):
create trigger _01_do_stuff ...
create trigger "01_do_stuff" ...
旁白:
FWIW,我最好的猜测是你的实际问题是你有两个或三个这些点,而MVCC对你不利。也就是说,触发器可能使PG将原始行标记为已死并插入新的实时行;随后的触发器(例如级联更新?)然后使PG标记新的实时行也是死的,导致另一个带有意外数据的实时行,并且术语可能会触发进一步的副作用的进一步触发。 / p>
换句话说,你的加注通知不是观察最后更新的行,而是一个被一个或多个后续更新压扁的中间行。观察所涉及的行的ctid
列应该揭示这一点,如果这确实是正在发生的事情。
最后,请注意explain analyze
将显示触发器在目标表上执行的顺序。 (最后我尝试了它,它没有显示级联触发器下降,但在最近的版本中可能已经改变了。)在调试触发器交互或识别性能问题时,使用该命令会很有用。
答案 1 :(得分:0)
在所涉及的表上设置了一些触发器,只是简单地发出了他们要调用的通知,我观察了以下一系列事件(尽管如此,由于上面的答案,EXPLAIN ANALYZE更容易实现这一点):
因此,触发器的命名仅影响其“本地”执行顺序。
无论如何,我最终将触发器设置为INITIALLY DEFERRED,并且完成了工作。虽然是的,但我同意,以这种方式使用触发器是微不足道的。