首页 > 解决方案 > “不可延迟的约束触发器”和正常的“事件后行级触发器”之间有什么区别吗?

问题描述

当检查约束时,我得到一个正常约束 [NOT] DEFERRABLE {INITIALLY IMMEDIATE/INITIALLY DEFERRED} 更改:在每个操作之后/每个语句之后/每个事务之后。同样对于可延迟触发器,我们可以使用“SET CONSTRAINTS”。

但似乎“不可延迟的约束触发器”在每行的语句末尾触发,就像正常的“事件后行级触发器”一样。同样对于此类触发器,我们不能使用 SET CONSTRAINTS,因为我们已将其声明为 NOT DEFERRABLE。

例如,在此代码中,触发器将所有可见的内容复制到名为“copy_example”的表中

CREATE TABLE example (
    ex INT);

CREATE TABLE copy_example (
    ex_copy INT);
    
CREATE FUNCTION save_copy()
RETURNS TRIGGER
LANGUAGE plpgsql
AS 
$$
BEGIN
    INSERT INTO copy_example (SELECT * FROM example);
    RETURN NEW;
END;
$$;

CREATE CONSTRAINT TRIGGER execute_copy
AFTER INSERT
ON example
NOT DEFERRABLE 
FOR EACH ROW
EXECUTE FUNCTION save_copy();

INSERT INTO example VALUES (1), (2);
SELECT * FROM copy_example; 

代码输出一个包含值 (1, 2, 1, 2) 而不是 (1, 1, 2) 的表,就像普通触发器一样。那么为什么要定义一个不可延迟的约束触发器而不是一个正常的触发器呢?他们的行为有什么不同吗?

标签: postgresql

解决方案


不,定义不可延迟的约束触发器是没有意义的。

该文档准确地描述了该行为:

指定选项时CONSTRAINT,此命令会创建一个约束触发器。这与常规触发器相同,只是可以使用 调整触发器触发的时间SET CONSTRAINTS。约束触发器必须是AFTER ROW普通表(不是外部表)上的触发器。它们可以在导致触发事件的语句结束时触发,也可以在包含事务结束时触发;在后一种情况下,它们被称为延迟。一个挂起的延迟触发触发也可以通过使用强制立即发生SET CONSTRAINTS。约束触发器应该在它们实现的约束被违反时引发异常。


推荐阅读