1
第十一章 管理触发器
? 触发器的概念
? 触发器的功能和类型
? 使用企业管理器创建和管理触发器
? 使用 T-SQL创建和管理触发器
2
? 触发器是一种特殊类型的存储过程, 它
不同于普通的存储过程 。 触发器主要是
通过事件进行触发而被执行的, 而存储
过程可以通过存储过程名称而被直接调
用 。 当往某一个表格中插入记录, 修改
记录或者删除记录时, SQL SERVER就
会自动执行触发器所定义的 SQL语句,
以确保数据的完整性 。
触发器的基本概念
3
? SQL SERVER可以检查数据完整性的还有什么
情况?
? 比 如 前面 讲过 的 CHECK 约束 。 但是, 与
CHECK约束相比, 触发器可以强制实现更加
复杂的数据完整性, 而且可以参考其他表的字
段 。
? 注意:触发器可以扩展 SQL Server 约束、默
认值和规则的完整性检查逻辑,但只要约束和
默认值提供了全部所需的功能,就应使用约束
和默认值。
4
触发器的作用
? 触发器可以使用 T-SQL语句进行复杂的
逻辑处理,它基于一个表创建,但是可
以对多个表进行操作,因此常常用于复
杂的业务规则。一般可以使用触发器完
成如下功能,
5
触发器的作用
? 1、级联修改数据库中相关的表。
? 例如:在数据库 company中有两个表 project和
customer,表 project中包含项目信息和项目的
合作客户名,而 customer表中则存储所有客户
的信息。如果删除了 customer表中的某一客户,
如张三,那么在 project表中所有和该客户有关
的项目记录都应该做相应的调整。如在 project
表中将所有合作客户为张三的字段改为 null或
者其它值,或者删除整条和张三有关的记录。
而使用触发器就可以实现这样的功能。
6
触发器的作用
? 2、执行比核查约束更为复杂的约束操作。
? 在触发器中可以书写更复杂的 T-SQL语
句,例如可以引用多个表,并使用
if…else 等语句做更复杂的检查。
? 3、拒绝或回滚违反引用完整性的操作。
检查对数据表的操作是否违反引用完整
性,并选择相应的操作。
7
触发器的作用
? 4、比较表修改前后数据之间的差别,并
根据差别采取相应的操作。例如:若想
规定每次工资的变动幅度不能超过 40%,
使用触发器可以将修改后的表数据和修
改前的表数据进行比较,若超出 40%,
可以回滚该修改操作。
8
触发器的类型
? 触发器可以分为五种类型,
? Update触发器:在表上进行更新操作时触
发。
? Insert触发器:在表上进行更新操作时触发
? Delete触发器:在表上进行更新操作时触

? Instead of触发器:不执行插入、更新或删
除操作时,将触发 Instead of 触发器。
? After触发器:在一个触发动作发生之后激
发,并提供一种机制以便控制多个触发器
的执行顺序。
9
SQL Server2000新增的触发器
? SQL Server 2000 新增了两种类型的触发器
AFTER 触发器和 INSTEAD OF 触发器 。 其中
AFTER 要求只有执行某一操作 ( INSERT、
UPDATE,DELETE ) 之后触发器才被触发,
且只能在表上定义 。 可以为针对表的同一操作
定义多个触发器 。 对于 AFTER 触发器, 可以
定义哪一个触发器被最先触发, 哪一个被最后
触发, 通常使用系统过程 sp_settriggerorder
来完成此任务 。
10
? INSTEAD OF 触发器表示并不执行其所
定义的操作 ( INSERT,UPDATE、
DELETE),而仅是执行触发器本身 。 既
可在表上定义 INSTEAD OF 触发器, 也
可以在视图上定义 INSTEAD OF 触发器,
但对同一操作只能定义一个 INSTEAD OF
触发器 。
11
触发器的主要优点
? 触发器是自动的:当对表中的数据作了任何修
改(比如手工输入或者应用程序采取的操作)
之后立即被激活。
? 触发器可以通过数据库中的相关表进行层叠更
改。
? 触发器可以强制限制,这些限制比用 CHECK
约束所定义的更复杂。而且比使用核查约束更
为方便的时,触发器可以引用其它数据表中的
列。
12
创建触发器的规则和限制
? 在创建和使用触发器时,需要遵循下列规则,
? Create Trigger语句必须是批处理中的第一个语
句,且该批处理中随后出现的其它所有语句都
将被解释为 Create Trigger语句定义的一部分。
? 在默认情况下,创建触发器的权限将分配给数
据表的所有者,且不能将该权限转给其它用户。
? 触发器是数据库对象,其名称必须遵循标识符
的命名规则。
? 虽然触发器可以引用当前数据库以外的对象,
但只能在当前数据库中创建触发器。
13
? 虽然不能在临时数据表上创建触发器,但是触
发器可以引用临时数据表。
? 既不能在系统数据表创建触发器,也不可以引
用系统数据表
? 在包含使用 delete或 update操作定义的外键的表
中,不能定义 instead of 和 instead of update 触
发器。
? 虽然 TRUNCATE TABLE 语句类似于没有
WHERE 子句(用于删除行)的 DELETE 语句,
但它并不会引发 DELETE 触发器,因为
TRUNCATE TABLE 语句没有被记入日志。
? Writetext语句不会引发 insert或 update触发器。
14
? 下面的语句不可以用于创建触发器,
? Alter Database,Create Database,Disk Init、
Disk Resize,Drop Database,Load Database、
Load Log,Reconfigure,Restore Database、
Restore Log。
? 当创建一个触发器时必须指定,⑴名称;⑵在
其上定义触发器的表;⑶触发器将何时激发;
⑷激活触发器的数据修改语句。
15
使用企业管理器管理触发器
? 创建触发器
? 修改触发器
? 删除触发器
16
? 1,打开企业管理器中, 然后展开要在其上创建
触发器的表 。
? 2,在表上单击鼠标右键, 然后在弹出菜单中选
择命令, 所有任务-管理触发器, 。
? 3,在, 触发器属性, 对话框内的名称栏中选择
,新建,
? 4,在, 文本, 文本框中输入创建触发器的 T-
SQL语句 。
? 5,按下窗口中的, 语法检查, 按钮, 若有错误,
修改文本框中的 SQL语句, 若没有错误, 则弹
出, 语法检查成功 !, 对话框 。
? 6,单击, 语法检查成功, 对话框中的, 确定,
按钮, 关闭, 触发器属性, 对话框, 即完成 。
创建触发器
17
修改触发器
? 1,打开企业管理器,并展开需要修改触发器
的表所在的数据库节点,然后选择将要修改的
触发器的表。
? 2、在表上单击鼠标右键,然后在弹出菜单中
选择命令“所有认为-管理触发器”
? 3、在“触发器属性”对话框中选择需要修改
的触发器名
? 4、在“文本”文本框中对触发器定义语句进
行修改。直到语法无错误为止。
? 5、关闭“触发器属性”对话框,修改完毕。
18
删除数据库
? 1,打开企业管理器,并展开需要修改触发器
的表所在的数据库节点,然后选择将要修改的
触发器的表。
? 2、在表上单击鼠标右键,然后在弹出菜单中
选择命令“所有认为-管理触发器”
? 3、在“触发器属性”对话框中选择需要删除
的触发器名
? 4、单击对话框中的“删除”按钮。
? 5、在“确定要删除触发器吗?”对话框中单
击“确定”按钮,确认删除。
19
使用 T-SQL管理触发器
? 创建触发器
? 查看触发器相关数据
? 修改触发器
? 删除触发器
20
创建触发器
?其语法形式如下,
?CREATE TRIGGER trigger_name
ON table|view
[WITH ENCRYPTION]
{ FOR | AFTER | INSTEAD OF }
{[INSERT][,][UPDATE][,][DELETE]}
AS
sql_statements […n]
各参数说明如下,
21
? 各参数的说明如下,
? trigger_name,是用户要创建的触发器的名字 。
触发器的名字必须符合 MS SQL Server 的命名规
则, 且其名字在当前数据库中必须是惟一的
? Table,是与用户创建的触发器相关联的表的名字,
并且该表已经存在 。
? WITH ENCRYPTION,表示对包含有 CREATE TRIGGER
文本的 syscomments 表进行加密
? [DELETE] [,] [INSERT] [,] [UPDATE],关键字
用来指明哪种数据操作将激活触发器, 至少要指
明一个选项, 在触发器的定义中三者的顺序不受
限制, 且各选项要用逗号隔开 。
22
? AFTER,表示只有在执行了指定的操作 INSERT、
DELETE,UPDATE 之后触发器才被激活, 执行
触发器中的 SQL语句 。 若使用关键字 FOR, 则
表示为 AFTER 触发器, 且该类型触发器仅能在
表上创建 。
? INSTEAD OF,当为表或视图定义了针对某一操
作 INSERT,DELETE,UPDATE 的
INSTEAD OF 类型触发器, 且执行了相应的操
作时, 尽管触发器被触发, 但相应的操作并不
被执行, 而运行的仅是触发器 SQL 语句本身 。
23
例子
? Use company
? Go
? --创建触发器
? Create trigger 触发器 _欢迎新员工
? On employee
? After insert
? As
? Print ‘新员工加入本公司,欢迎欢迎!’
? go
24
? --创建触发器
? Create trigger 触发器 _员工走了
? On employee
? After delete
? As
? Print ‘真遗憾你离开公司!’
? go
25
? Set nocount on
? --插入一条记录试试触发器操作
? Insert into employee(员工 id,姓名,性别,工资 )
? Values(20068,’赵一’,‘男’,1000)
? --删除一条记录试试
? Delete from employee
? Where 员工 id = ‘20067’
? go
26
查看触发器相关数据
? 1,查看表中存在哪些相关触发器
? 使用企业管理器查看:打开企业管理器,
在表上单击鼠标右键,然后选择命令
“所有任务-管理触发器”,则在“触
发器属性”窗口可以看到新建的触发器。
27
查看触发器相关数据
? 使用系统存储过程 sp_helptrigger,语法
如下,exec sp_helptrigger ‘table’
[,’type’]
? 其中,table,触发器所在的表名
? Type,指定列出的操作类型的触发器。
若不指定,则列出所有的触发器。
? 例如,exec sp_helptrigger ‘employee’
28
查看触发器的定义文本
? 使用企业管理器查看:在企业管理器的
“触发器属性”窗口查看,也可以打开
系统表 syscomments查看。
29
查看触发器的定义文本
? 触发器的定义文本存储在系统表
syscomments中,但是可以通过执行系统存
储过程 sp_helptext进行查看,执行该存储过
程的语法格式如下,
? Sp_helptext ‘trigger_name’
? 例如,exec sp_helptext ‘触发器 _欢迎新员工 ’
? 注意:若在定义触发器时对定义文本进行加
密处理,则不能使用任何方法查看触发器的
定义文本。
30
查看触发器的所有者和创建日期
? 可以使用系统存储过程 sp_help,其格式
如下,
? Exec sp_help ‘trigger_name’
? 例如,exec sp_help ‘触发器 _欢迎新员工’
31
修改触发器
? 若希望对现有触发器进行修改,可以使用 alter
trigger 语句,其语法格式如下,
? ALTER TRIGGER trigger_name
ON table|view
[WITH ENCRYPTION]
{FOR | AFTER | INSTEAD OF }
{ [DELETE] [,][INSERT][,][UPDATE]}
AS
sql_statement[...n]
注意:就是创建触发器的语句中的 create换为
alter,其余部分完全相同。但是在 alter
trigger中引用的触发器名必须是已经存在的触
发器名
32
触发器更名
? 使用系统存储过程 sp_rename完成。其语法格

如下,
? sp_rename oldname,newname
? 例如:将触发器“触发器 _欢迎新员工”更名
为 welcome_Trigger,
? Exec sp_rename ‘触发器 _欢迎新员
工’,‘ welcom_trigger’
33
删除触发器
? 使用 drop trigger语句,语法如下,
? Drop trigger trigger_name [,…n]
? 其中 trigger_name是触发器名称,可以
同时删除多个触发器。
? 例如,drop trigger 触发器 _员工走了
? 注意:当删除数据表时,也将同时删除
所有与该数据表相关联的触发器。而且
当删除触发器时,系统也将从 sysobjects
和 syscomments系统表中删除有关该触
发器的信息。
34
确保数据完整性
? Sp_dboption pubs,’select into’,true
? Go
? Select * into tblstores from pubs..stores
? Select * into tblsales from pubs..sales
? go
35
? select sa.stor_id,st.stor_name
? from tblstores st,tblsales sa
? where st.stor_id=sa.stor_id
? go
? create trigger trDelAuthors
? on tblsales
? for delete as
? raiserror('%d rows are going to be deleted
from the sales table!',0,1,@@rowcount)
36
? Create trigger trDelSales
? On tblStores
? For Delete As
? Delete tblsales from deleted where
deleted.stor_id=tblSales.stor_id
? 最后,继续删除 stor_id7067,即,news &
brews”商店
? Delete from tblstores
? Where tblstores.stor_id=‘7067’
37
封装事务规则
? Create Trigger trDelSales
? On tblSales
? For Delete As
? If (Select Count(*) from Deleted
? Where Deleted.qty>=20)>0
? Begin
? Print 'you cannot delete any of these stores'
? Print 'some stores have more than 20 sales!'
? Print 'Rolling back your transaction!'
? Rollback Transaction
? end
38
? Delete From tblSales
? Where stor_id=‘7066’
? 至少有一个商店( stor_id=‘7066’ )有不少于
20条的销售记录,为了验证是否如此,运行
select语句,
? select stor_id,qty from tblsales
? 现在用 stor_id=6380再次运行 delete语句,正如
预计的那样,这会删除 qty域不多于 20条的商店。
? Delete from tblsales where stor_id=‘6380’
39
确保引用完整性
? Create trigger trInsUpdSales On tblSales
? For insert,Update As
? If (select count(*) from tblstores,inserted
? Where tblstores.stor_id=inserted.stor_id)=0
? Begin
– Print 'the stor_id you have entered does not exist'
– Print 'in the stores table!'
– Rollback transaction
? End
? 触发器将会对任何单个的 Update和 Insert行为发生作用,
确保在 tblstores表中的都是有效的 stor_id。 然而,如果运行
select into,触发器将不能正确触发。当需要多个行时,应
进行检查以确保插入的 stor_id的 rowcount= 加入的小手记
录总数。
40
? Create trigger trInsUpdSales
? On tblSales for Insert,Update as
? Declare @rc int
? Select @rc=@@rowcount
? If (select count(*) from tblstores,inserted
? Where tblstores.stor_id=inserted.stor_id)=0
? Begin
– Print 'the stor_id you have entered does not exist'
– Print 'in the stores table!'
– Rollback transaction
? End
? If (select count(*) from tblStores,inserted
? Where tblStores.stor_id=inserted.stor_id)<>@rc
? Begin
– Print 'not all sales have a valid stor_id'
– Print 'in the stores table!'
– Rollback transaction
? End
41
使用嵌套的触发器
? 如果一个触发器在执行操作时引发了另一个触
发器, 而这个触发器又接着引发下一个触发
器 …… 这些触发器就是嵌套触发器 。 触发器可
嵌套至 32 层, 并且可以控制是否可以通过
,嵌套触发器, 服务器配置选项进行触发器嵌
套 。 如果允许使用嵌套触发器, 且链中的一个
触发器开始一个无限循环, 则超出嵌套级, 而
且触发器将终止 。 在执行过程中, 如果一个触
发器修改某个表, 而这个表已经有其它触发器,
这时就要使用嵌套触发器 。