再进入和级联触发器

触发器不能再进入的情况中递归应用于所有的级联触发器。它被认为是初始触发器的一部分。特别地,该规则表示级联触发器不能更新原始触发语句更新的触发表中的任何列,包括该语句影响的任何非触发列。例如,假设此 UPDATE 语句是触发语句:
UPDATE tab1 SET (a, b) = (a + 1, b + 1);
在下一个示例的级联触发器中,trig2 在运行时失败,因为它引用触发 UPDATE 语句更新的列 b
CREATE TRIGGER trig1 UPDATE OF a ON tab1-- Valid
        AFTER (UPDATE tab2 SET e = e + 1);
        
        CREATE TRIGGER trig2 UPDATE OF e ON tab2-- Invalid
        AFTER (UPDATE tab1 SET b = b + 1);

现在考虑以下 SQL 语句,当执行最终的 UPDATE 语句时,列 a 被更新且触发器 trig1 被激活。

触发操作再次用 EXECUTE PROCEDURE INTO 语句更新列 a
CREATE TABLE temp1 (a INT, b INT, e INT);
        INSERT INTO temp1 VALUES (10, 20, 30);
        
        CREATE PROCEDURE proc(val iINT) RETURNING INT,INT;
        RETURN val+10, val+20;
        END PROCEDURE;
        
        CREATE TRIGGER trig1 UPDATE OF a ON temp1
        FOR EACH ROW (EXECUTE PROCEDURE proc(50) INTO a, e);
        
        CREATE TRIGGER trig2 UPDATE OF e ON temp1
        FOR EACH ROW (EXECUTE PROCEDURE proc(100) INTO a, e);
        
        UPDATE temp1 SET (a,b) = (40,50);

该级联触发器示例有几个问题。首先,更新列 a 是否会再次激活触发器 trig1 ?答案是否定的。因为触发器已被激活,它没有被再次激活。如果触发操作是 EXECUTE PROCEDURE INTO 或 EXECUTE FUNCTION INTO 语句,只有那些从更新的列到之后(在触发器级联中)在该表中互斥的列上定义的触发器才被激活。其它触发器被忽略。

该示例产生的另一个问题是触发器 trig2 是否被激活。答案是肯定的。触发器 trig2 在列 e 上定义。直到现在,表 temp1 中的列 e 尚未被修改。触发器 trig2 被激活。

该示例产生的最后一个问题是执行 trig2 中您的触发操作后触发器 trig1trig2 是否被激活。答案是否定的。两个触发器都不会被激活。在此之前列 ae 已被更新一次,触发器 trig1trig2 已被执行一次。数据库服务器忽略这些触发器且不激活它们。关于级联触发器的更多信息,请参阅级联触发器

正如前面提到的,视图上的 INSTEAD OF 触发器在其它触发器操作中不能包含 EXECUTE PROCEDURE INTO 语句。而且,如果两个视图分别具有带有已定义的操作(在其它视图上执行插入操作)的 INSERT INSTEAD OF 触发器的话,会产生错误。