如果一个触发器在执行操作时引发了另一个触发器,而这个触发器又接着引发下一个触发器……这些触发器就是嵌套触发器。触发器可嵌套至 32 层,并且可以控制是否可以通过"嵌套触发器"服务器配置选项进行触发器嵌套。

如果允许使用嵌套触发器,且链中的一个触发器开始一个无限循环,则超出嵌套级,而且触发器将终止。

可使用嵌套触发器执行一些有用的日常工作,如保存前一触发器所影响行的一个备份。例如,可以在 titleauthor 上创建一个触发器,以保存由 delcascadetrig 触发器所删除的 titleauthor 行的备份。在使用 delcascadetrig 时,从 titles 中删除title_id PS2091 将删除 titleauthor 中相应的一行或多行。要保存数据,可在 titleauthor 上创建 DELETE 触发器,该触发器的作用是将被删除的数据保存到另一个单独创建的名为 del_save

CREATE TRIGGER savedel
ON titleauthor
FOR DELETE
AS
INSERT del_save
SELECT * FROM deleted

不推荐按依赖于顺序的序列使用嵌套触发器。应使用单独的触发器层叠数据修改。

说明

递归触发器

触发器不会以递归方式自行调用,除非设置了 RECURSIVE_TRIGGERS 数据库选项。有两种不同的递归方式:

  • 直接递归即触发器激发并执行一个操作,而该操作又使同一个触发器再次激发。例如,一应用程序更新了表T3,从而引发触发器 Trig3Trig3 再次更新表 T3,使触发器 Trig3
  • 间接递归即触发器激发并执行一个操作,而该操作又使另一个表中的某个触发器激发。第二个触发器使原始表得到更新,从而再次引发第一个触发器。例如,一应用程序更新了表T1,并引发触发器 Trig1Trig1 更新表 T2,从而使触发器 Trig2 被引发。Trig2 转而更新表 T1,从而使 Trig1

当将 RECURSIVE_TRIGGERS 数据库选项设置为 OFF 时,仅防止直接递归。若要也禁用间接递归,请将 nested triggers

示例
A. 使用递归触发器解决自引用关系

递归触发器的一种用法是用于带有自引用关系的表(亦称为传递闭包)。例如,表 emp_mgr

  • 一个公司的雇员 (emp)。
  • 每个雇员的经理 (mgr)。
  • 组织树中向每个经理汇报的雇员总数 (NoOfReports)。

递归 UPDATE 触发器在插入新雇员记录的情况下可以使 NoOfReports 列保持最新。INSERT 触发器更新经理记录的 NoOfReports 列,而该操作递归更新管理层向上其它记录的 NoOfReports 列。

 1


使用嵌套触发器_null

USE

 pubs

 2

使用嵌套触发器_null

GO

 3

使用嵌套触发器_null

--  Turn recursive triggers ON in the database.

 4

使用嵌套触发器_null

ALTER   DATABASE  pubs

 5

使用嵌套触发器_null

   

SET  RECURSIVE_TRIGGERS  ON

 6

使用嵌套触发器_null

GO

 7

使用嵌套触发器_null

CREATE   TABLE  emp_mgr (

 8

使用嵌套触发器_null

   emp 

char ( 30 )  PRIMARY   KEY ,

 9

使用嵌套触发器_null

    mgr 

char ( 30 )  NULL   FOREIGN   KEY   REFERENCES  emp_mgr(emp),

10

使用嵌套触发器_null

    NoOfReports 

int   DEFAULT   0

11

使用嵌套触发器_null

)

12

使用嵌套触发器_null

GO

13

使用嵌套触发器_null

CREATE   TRIGGER  emp_mgrins  ON  emp_mgr

14

使用嵌套触发器_null

FOR   INSERT

15

使用嵌套触发器_null

AS

16

使用嵌套触发器_null

DECLARE   @e   char ( 30 ),  @m   char ( 30 )

17

使用嵌套触发器_null

DECLARE  c1  CURSOR   FOR

18

使用嵌套触发器_null

   

SELECT  emp_mgr.emp

19

使用嵌套触发器_null

   

FROM    emp_mgr, inserted

20

使用嵌套触发器_null

   

WHERE  emp_mgr.emp  =  inserted.mgr

21

使用嵌套触发器_null


22

使用嵌套触发器_null

OPEN  c1

23

使用嵌套触发器_null

FETCH   NEXT   FROM  c1  INTO   @e

24

使用嵌套触发器_null

WHILE   @@fetch_status   =   0

25

使用嵌套触发器_null

BEGIN

26

使用嵌套触发器_null

   

UPDATE  emp_mgr

27

使用嵌套触发器_null

   

SET  emp_mgr.NoOfReports  =  emp_mgr.NoOfReports  +   1   --  Add 1 for newly

28

使用嵌套触发器_null

    WHERE  emp_mgr.emp  =   @e                              --  added employee.

29

使用嵌套触发器_null


30

使用嵌套触发器_null

   

FETCH   NEXT   FROM  c1  INTO   @e

31

使用嵌套触发器_null

END

32

使用嵌套触发器_null

CLOSE  c1

33

使用嵌套触发器_null

DEALLOCATE  c1

34

使用嵌套触发器_null

GO

35

使用嵌套触发器_null

--  This recursive UPDATE trigger works assuming:

36

使用嵌套触发器_null

--

   1. Only singleton updates on emp_mgr.

37

使用嵌套触发器_null

--

   2. No inserts in the middle of the org tree.

38

使用嵌套触发器_null

CREATE   TRIGGER  emp_mgrupd  ON  emp_mgr  FOR   UPDATE

39

使用嵌套触发器_null

AS

40

使用嵌套触发器_null

IF   UPDATE  (mgr)

41

使用嵌套触发器_null

BEGIN

42

使用嵌套触发器_null

   

UPDATE  emp_mgr

43

使用嵌套触发器_null

   

SET  emp_mgr.NoOfReports  =  emp_mgr.NoOfReports  +   1   --  Increment mgr's

44

使用嵌套触发器_null

    FROM  inserted                             --  (no. of reports) by

45

使用嵌套触发器_null

    WHERE  emp_mgr.emp  =  inserted.mgr          --  1 for the new report.

46

使用嵌套触发器_null


47

使用嵌套触发器_null

   

UPDATE  emp_mgr

48

使用嵌套触发器_null

   

SET  emp_mgr.NoOfReports  =  emp_mgr.NoOfReports  -   1   --  Decrement mgr's

49

使用嵌套触发器_null

    FROM  deleted                              --  (no. of reports) by 1

50

使用嵌套触发器_null

    WHERE  emp_mgr.emp  =  deleted.mgr           --  for the new report.

51

使用嵌套触发器_null

END

52

使用嵌套触发器_null

GO

53

使用嵌套触发器_null

--  Insert some test data rows.

54

使用嵌套触发器_null

INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Harry ' ,  NULL )

55

使用嵌套触发器_null

INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Alice ' ,  ' Harry ' )

56

使用嵌套触发器_null

INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Paul ' ,  ' Alice ' )

57

使用嵌套触发器_null

INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Joe ' ,  ' Alice ' )

58

使用嵌套触发器_null

INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Dave ' ,  ' Joe ' )

59

使用嵌套触发器_null

GO

60

使用嵌套触发器_null

SELECT   *   FROM  emp_mgr

61

使用嵌套触发器_null

GO

62

使用嵌套触发器_null

--  Change Dave's manager from Joe to Harry

63

使用嵌套触发器_null

UPDATE  emp_mgr  SET  mgr  =   ' Harry '

64

使用嵌套触发器_null

WHERE  emp  =   ' Dave '

65

使用嵌套触发器_null

GO

66

使用嵌套触发器_null

SELECT   *   FROM  emp_mgr

67

使用嵌套触发器_null

GO

68

使用嵌套触发器_null


69

使用嵌套触发器_null

以下是更新前的结果:

70

使用嵌套触发器_null


71

使用嵌套触发器_null

emp                            mgr                           NoOfReports

72

使用嵌套触发器_null

-- ---------------------------- ----------------------------- -----------

73

使用嵌套触发器_null

Alice                          Harry                           2

74

使用嵌套触发器_null

Dave                           Joe                            

0

75

使用嵌套触发器_null

Harry                          

NULL                             1

76

使用嵌套触发器_null

Joe                            Alice                          

1

77

使用嵌套触发器_null

Paul                           Alice                          

0

78

使用嵌套触发器_null


79

使用嵌套触发器_null

以下为更新后的结果:

80

使用嵌套触发器_null


81

使用嵌套触发器_null

emp                            mgr                           NoOfReports

82

使用嵌套触发器_null

-- ---------------------------- ----------------------------- -----------

83

使用嵌套触发器_null

Alice                          Harry                           2

84

使用嵌套触发器_null

Dave                           Harry                          

0

85

使用嵌套触发器_null

Harry                          

NULL                             2

86

使用嵌套触发器_null

Joe                            Alice                          

0

87

使用嵌套触发器_null

Paul                           Alice                          

0