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

相关文章:

  • 2022-12-23
  • 2022-02-09
  • 2022-12-23
  • 2022-01-02
  • 2021-07-14
  • 2021-07-11
  • 2022-02-01
  • 2021-06-04
猜你喜欢
  • 2021-07-31
  • 2022-02-24
  • 2021-07-02
  • 2021-07-26
  • 2022-12-23
  • 2022-02-11
  • 2021-11-09
相关资源
相似解决方案