使用“ON CONFLICT DO NOTHING”进行INSERT触发器

4
我在Postgres 9.5+中有一个INSERT语句,但由于关键冲突(我在INSERT上设置了ON CONFLICT DO NOTHING),该INSERT有时实际上不会发生。
如果INSERT发生,则触发器当然会运行。但是,如果由于关键冲突而INSERT未发生,触发器是否仍会运行?这取决于触发器是BEFORE还是AFTER触发器吗?

1
insert触发器不会运行,因为没有可执行的行。如果你执行了update操作,那么会触发一个更新触发器。 - Gordon Linoff
1个回答

5
每行BEFORE INSERT触发器在检查冲突之前被触发,并应用于提议的行可能产生的影响。 手册:

请注意,所有每行 BEFORE INSERT 触发器的效果都会反映在排除值中,因为这些效果可能已导致将行从插入中排除。

普通的INSERT 将引发一个EXCEPTION ,因为唯一性冲突,这将回滚所有内容(除了无法回滚的内容,如递增序列)。
但是带有 ON CONFLICT DO NOTHING的UPSERT会抑制异常,因此任何此类触发器的影响仍然存在,即使跳过了拟议插入的行。
(因此,在使用 ON CONFLICT DO UPDATE ...时,这些触发器的影响反映在可见的UPDATE 部分中的特殊EXCLUDED 行中。)
但是,AFTER INSERT 触发器没有被触发甚至不会为任何一种情况触发。实际上从来没有插入这行数据,不管是否引发异常。
我考虑使用RULE ,它可以将 INSERT 重写为运行附加命令,与结果无关。比触发器更棘手,但它在可能取消 INSERT 之前触发。然而,手册警告:

请注意,包含 ON CONFLICT 子句的INSERT 不能用于具有INSERT UPDATE 规则的表。考虑使用可更新的视图。

所以,不行。

@user779159:我的原始答案是不正确的。请考虑重写。 - Erwin Brandstetter

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接