使用嵌套触发器

如果一个触发器在执行操作时引发了另一个触发器,而这个触发器又接着引发下一个触发器……这些触发器就是嵌套触发器。触发器可嵌套至 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

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

说明  由于触发器在事务中执行,如果在一系列嵌套触发器的任意层中发生错误,则整个事务都将取消,且所有的数据修改都将回滚。在触发器中包含 PRINT 语句,用以确定错误发生的位置。

递归触发器

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

  • 直接递归

    即触发器激发并执行一个操作,而该操作又使同一个触发器再次激发。例如,一应用程序更新了表 T3,从而引发触发器 Trig3Trig3 再次更新表 T3,使触发器 Trig3 再次被引发。

  • 间接递归

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

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

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

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

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

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

 1 USE  pubs
 2 GO
 3 --  Turn recursive triggers ON in the database.
 4 ALTER   DATABASE  pubs
 5     SET  RECURSIVE_TRIGGERS  ON
 6 GO
 7 CREATE   TABLE  emp_mgr (
 8    emp  char ( 30 PRIMARY   KEY ,
 9     mgr  char ( 30 NULL   FOREIGN   KEY   REFERENCES  emp_mgr(emp),
10     NoOfReports  int   DEFAULT   0
11 )
12 GO
13 CREATE   TRIGGER  emp_mgrins  ON  emp_mgr
14 FOR   INSERT
15 AS
16 DECLARE   @e   char ( 30 ),  @m   char ( 30 )
17 DECLARE  c1  CURSOR   FOR
18     SELECT  emp_mgr.emp
19     FROM    emp_mgr, inserted
20     WHERE  emp_mgr.emp  =  inserted.mgr
21
22 OPEN  c1
23 FETCH   NEXT   FROM  c1  INTO   @e
24 WHILE   @@fetch_status   =   0
25 BEGIN
26     UPDATE  emp_mgr
27     SET  emp_mgr.NoOfReports  =  emp_mgr.NoOfReports  +   1   --  Add 1 for newly
28     WHERE  emp_mgr.emp  =   @e                              --  added employee.
29
30     FETCH   NEXT   FROM  c1  INTO   @e
31 END
32 CLOSE  c1
33 DEALLOCATE  c1
34 GO
35 --  This recursive UPDATE trigger works assuming:
36 --    1. Only singleton updates on emp_mgr.
37 --    2. No inserts in the middle of the org tree.
38 CREATE   TRIGGER  emp_mgrupd  ON  emp_mgr  FOR   UPDATE
39 AS
40 IF   UPDATE  (mgr)
41 BEGIN
42     UPDATE  emp_mgr
43     SET  emp_mgr.NoOfReports  =  emp_mgr.NoOfReports  +   1   --  Increment mgr's
44     FROM  inserted                             --  (no. of reports) by
45     WHERE  emp_mgr.emp  =  inserted.mgr          --  1 for the new report.
46
47     UPDATE  emp_mgr
48     SET  emp_mgr.NoOfReports  =  emp_mgr.NoOfReports  -   1   --  Decrement mgr's
49     FROM  deleted                              --  (no. of reports) by 1
50     WHERE  emp_mgr.emp  =  deleted.mgr           --  for the new report.
51 END
52 GO
53 --  Insert some test data rows.
54 INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Harry ' NULL )
55 INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Alice ' ' Harry ' )
56 INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Paul ' ' Alice ' )
57 INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Joe ' ' Alice ' )
58 INSERT  emp_mgr(emp, mgr)  VALUES  ( ' Dave ' ' Joe ' )
59 GO
60 SELECT   *   FROM  emp_mgr
61 GO
62 --  Change Dave's manager from Joe to Harry
63 UPDATE  emp_mgr  SET  mgr  =   ' Harry '
64 WHERE  emp  =   ' Dave '
65 GO
66 SELECT   *   FROM  emp_mgr
67 GO
68
69 以下是更新前的结果:
70
71 emp                            mgr                           NoOfReports
72 -- ---------------------------- ----------------------------- -----------
73 Alice                          Harry                           2
74 Dave                           Joe                             0
75 Harry                           NULL                             1
76 Joe                            Alice                           1
77 Paul                           Alice                           0
78
79 以下为更新后的结果:
80
81 emp                            mgr                           NoOfReports
82 -- ---------------------------- ----------------------------- -----------
83 Alice                          Harry                           2
84 Dave                           Harry                           0
85 Harry                           NULL                             2
86 Joe                            Alice                           0
87 Paul                           Alice                           0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值