• 沒有找到結果。

5.3.1 触发器的概念

触发器是一类特殊的存储过程,它与表紧密相连,在对特定表或视图发出 UPDATE、INSERT 或 DELETE 语句时自动执行。

Microsoft SQL Server 2008 提供了两种主要机制来强制执行业务规则和数据完整性:约束和触 发器。

注意:触发器不需要调用,也不传递参数或接受参数,当对一个表的特殊事件出现时,它就 会被激活,主要作用就是实现由主键和外键所不能保证的复杂的参照完整性和数据一致性。

5.3.2 触发器的作用

(1)完成比约束更复杂的数据约束。触发器可以实现比约束更为复杂的数据约束。

(2)检查所做的 SQL 是否允许。触发器可以检查 SQL 所做的操作是否被允许,例如,在产 品库存表里,如果要删除一条产品记录,在删除记录时,触发器可以检查该产品库存数量是否为零,

如果不为零则取消该删除操作。

(3)修改其他数据表里的数据。当一个 SQL 语句对数据表进行操作时,触发器可以根据该 SQL 语句的操作情况来对另一个数据表进行操作。例如,一个订单取消的时候,触发器可以自动 修改产品库存表,在订购量的字段上减去被取消订单的订购数量。

(4)调用更多的存储过程。约束的本身是不能调用存储过程的,但是触发器本身就是一种存 储过程,而存储过程是可以嵌套使用的,所以触发器也可以调用一个或多个存储过程。

(5)发送 SQL Mail。在 SQL 语句执行完成后,触发器可以判断更改过的记录是否达到一定 条件,如果达到这个条件,触发器可以自动调用 SQL Mail 来发送邮件。例如,当一个订单交费之 后,可以向物流人员发送 Email,通知他尽快发货。

(6)返回自定义的错误信息。约束是不能返回信息的,而触发器可以。例如插入一条重复记 录时,可以返回一个具体的友好的错误信息给前台应用程序。

(7)更改原本要操作的 SQL 语句。触发器可以修改原本要操作的 SQL 语句,例如原本的 SQL 语句是要删除数据表里的记录,但该数据表里的记录是重要记录,不允许删除,那么触发器可以不 执行该语句。

(8)防止数据表结构更改或数据表被删除。为了保护已经建好的数据表,触发器可以在接收 到 DROP 和 ALTER 开头的 SQL 语句里不进行对数据表的操作。

5.3.3 触发器的种类 1.DML 触发器

DML 触发器是当数据库服务器中发生数据操纵语言(Data Manipulation Language)事件时执 行的存储过程。DML 事件包括在指定表或视图中修改数据的 INSERT 语句、UPDATE 语句、DELETE 语句。DML 触发器可以查询其他表,还可以包含复杂的 T-SQL 语句。

2.DDL 触发器

当服务器或数据库中发生数据定义语言(DDL)事件时将调用这些触发器。但与 DML 触发 器不同的是,它们不会为响应针对表或视图的 UPDATE、INSERT、DELETE 语句而激发,相反,

它们会为响应多种数据定义语言(DDL)语句而激发。这些语句主要是以 CREATE、ALTER 和 DROP 开头的语句。DDL 触发器可用于管理任务,如审核和规范数据库操作、防止数据库表结 构被修改等。

5.3.4 DML触发器的分类

(1)After 触发器:这类触发器是在记录已经改变完之后(after)才会被激活执行,它主要是用 于记录变更后的处理或检查,一旦发现错误,也可以用 Rollback Transaction 语句来回滚本次的操作。

(2)Instead Of 触发器:这类触发器一般是用来取代原本的操作,是在记录变更之前发生的,

它并不去执行原来 SQL 语句里的操作(INSERT、UPDATE、DELETE),而去执行触发器本身所定 义的操作。

5.3.5 DML触发器的工作原理

在 SQL Server 2008 里,为每个 DML 触发器都定义了两个特殊的表:一个是插入表(Inserted),

一个是删除表(Deleted)。

这两个表是建在数据库服务器的内存中的,是由系统管理的逻辑表,而不是真正存储在数据库 中的物理表。对于这两个表,用户只有读取的权限,没有修改的权限。

这两个表的结构与触发器所在数据表的结构是完全一致的,当触发器的工作完成之后,这两个 表也将会从内存中删除。

插入表(Inserted)里存放的是更新前的记录:对于插入记录操作来说,插入表里存放的是要

插入的数据;对于更新记录操作来说,插入表里存放的是要更新的记录。

删除表(Deldeted)里存放的是更新后的记录:对于更新记录操作来说,删除表里存放的是更 新前的记录(更新完后即被删除);对于删除记录操作来说,删除表里存放的是被删除的旧记录。

1.After 触发器的工作原理

After 触发器是在记录变更完成之后(如果是存储过程,而且有事务,则要在事务提交之后)

才会被激活并执行的。以删除记录为例,分为以下步骤:

(1)当 SQL Server 接收到一个要执行删除操作的 SQL 语句时,SQL Server 先将要删除的记 录存放在删除表里。

(2)把数据表里的记录删除。

(3)激活 After 触发器,执行 After 触发器里的 SQL 语句。

(4)触发器执行完毕之后,删除内存中的删除表,退出整个操作。

例如,在产品库存表里,如果要删除一条产品记录,在删除记录时,触发器可以检查该产品库 存数量是否为零,如果不为零则取消删除操作。看一下数据库是怎么操作的:

(1)接收 SQL 语句,将要从产品库存表里删除的产品记录取出来,放在删除表里。

(2)从产品库存表里删除该产品记录。

(3)从删除表里读出该产品的库存数量字段,判断是否为零,如果为零,则完成操作,从内 存里清除删除表;如果不为零,则用 Rollback Transaction 语句来回滚操作。

2.Instead Of 触发器的工作原理

Instead Of 触发器与 After 触发器不同。After 触发器是在 INSERT、UPDATE 和 DELETE 操作 完成后才激活的,而 Instead Of 触发器是在这些操作进行之前就激活了,并且不再去执行原来的 SQL 操作,而去运行触发器本身的 SQL 语句。

5.3.6 设计 DML 触发器的注意事项及技巧

在了解触发器的种类和工作原理之后,现在可以开始动手来设计触发器了,不过在动手之前,

还有一些注意事项必须先了解一下。

1.设计触发器的限制

在触发器中,有一些 SQL 语句是不能使用的,这些语句如表 5.6 所示。

表 5.6 在 DML 触发器中不能使用的语句

不能使用的语句 语句功能

ALTER DATABASE 修改数据库

CREATE DATABASE 新建数据库

DROP DATABASE 删除数据库

LOAD DATABASE 导入数据库

LOAD LOG 导入日志

RECONFIGURE 更新配置选项

RESTORE DATABASE 还原数据库

RESTORE LOG 还原数据库日志

另外,在对作为触发操作的目标的表或视图使用了如表 5.7 所示的 SQL 语句时,不允许在 DML

触发器里再使用这些语句。

表 5.7 在目标表中使用过的 DML 触发器不能再使用的语句

不能使用的语句 语句功能

CREATE INDEX 建立索引

ALTER INDEX 修改索引

DROP INDEX 删除索引

DBCC DBREINDEX 重新生成索引

ALTER PARTITION FUNCTION 通过拆分或合并边界值更改分区

DROP TABLE 删除数据表

ALTER TABLE 修改数据表结构

2.如何在触发器中取得字段修改前和修改后的数据

上面介绍过,SQL Server 2008 为每个触发器都定义了两个虚拟表:一个是插入表(Inserted),

一个是删除表(Deleted),现在把这两个表存放的数据列表说明一下,如表 5.8 所示。

表 5.8 插入/删除表的功能

激活触发器的动作 Inserted 表 Deleted 表

INSERT 存放要插入的记录

UPDATE 存放要更新的记录 存放更新前的旧记录

DELETE 存放要删除的旧记录

【例 5.27】删除库存产品记录时,在删除时触发器要判断库存数量是否为零。

IF(SELECT 库存数量 FROM deleted)>0 BEGIN

PRINT '库存数量大于 0 时不能删除此记录' Rollback transaction

END

3.使用 DML 触发器的注意事项

(1)After 触发器只能用于数据表中,Instead Of 触发器可以用于数据表和视图上,但两种触 发器都不可以建立在临时表上。

(2)一个数据表可以有多个触发器,但是一个触发器只能对应一个表。

(3)在同一个数据表中,对每个操作(如 INSERT、UPDATE、DELETE)而言可以建立许多 个 After 触发器,但 Instead Of 触发器针对每个操作只能建立一个。

(4)如果针对某个操作既设置了 After 触发器又设置了 Instead Of 触发器,那么 Instead of 触 发器一定会激活,而 After 触发器就不一定会激活。

(5)Truncate Table 语句虽然类似于 Delete 语句可以删除记录,但是它不能激活 Delete 类型的 触发器,因为 Truncate Table 语句是不记入日志的。

(6)WRITETEXT 语句不能触发 INSERT 和 UPDATE 型的触发器。

(7)不同的 SQL 语句可以触发同一个触发器,如 INSERT 和 UPDATE 语句都可以激活同一 个触发器。

5.3.7 创建 DML 触发器

创建 DML 触发器有两种方法:一种是用 SSMS 创建触发器,一种是用 T-SQL 语言创建触发器。

1.在 SSMS 中创建触发器

通过 SSMS 创建触发器的步骤如下:

(1)启动 SSMS,连接到数据库实例,在“对象资源管理器”对话框中选择“数据库实例”

→“数据库”→NORTHWIND→“表”→Products→“触发器”并右击,在弹出的快捷菜单中选择

“新建触发器”选项,如图 5.6 所示。

图 5.6 定位到触发器对话框

(2)打开“创建触发器”模板,如图 5.7 所示。

图 5.7 “创建触发器”模板

(3)在“创建触发器”模板中,修改其代码,或者是选择“查询”→“指定参数的模板”选 项,弹出“指定模板参数的值”对话框,如图 5.8 所示。

图 5.8 “指定模板参数的值”对话框

(4)指定模板参数后,在模板里修改其他代码,然后单击“运行”按钮,完成触发器的创建。

(5)修改查询编辑器里的代码,将从“CREATE”开始到“GO”结束的代码改为以下代码:

CREATE TRIGGER 产品_Insert ON products

AFTER INSERT AS

BEGIN

PRINT '又添加了一种产品' END

GO

(6)关掉查询编辑器模板,刷新一下触发器对话框,可以看到刚才建立的 procudt_Insert 触发器。

建立 After Update 触发器、After Delete 触发器和建立 After Insert 触发器的步骤一致,不同的 地方是把上面的 SQL 语句中的 AFTER INSERT 分别改为 AFTER UPDATE 和 AFTER DELETE 即 可,如下所示,有兴趣的读者可以自行测试:

CREATE TRIGGER 产品_Update ON 产品

AFTER UPDATE AS

BEGIN

PRINT '有一种产品更改了'

PRINT '有一种产品更改了'

相關文件