第42章认识触发器
触发器与存储过程非常相似,触发器也是SQL语句集,两者惟一的区别是触发器不能用EXECUTE语句调用,而是在用户执行Transact-SQL语句时自动触发(激活)执行。下面将对触发器的概念以及类型进行详细介绍。
42.1  触发器概述
触发器是一个在修改指定表中的数据时执行的存储过程。经常通过创建触发器来强制实现不同表中的逻辑相关数据的引用完整性或者一致性。由于用户不能绕过触发器,所以可以用来强制实施复杂的业务规则,以此确保数据的完整性。
触发器不同于前面介绍的存储过程。触发器主要是通过事件进行触发而被执行的,而存储过程可以通过存储过程名字而被直接调用。当对某一表进行诸如UPDATE、INSERT、DELETE这些操作时,SQL Server就会自动执行触发器所定义的SQL语句,从而确保对数据的处理必须符合由这些SQL语句所定义的规则。
1.触发器的作用
触发器的主要作用就是其能够实现由主键和外键所不能保证的复杂的参照完整性和数据的一致性。能够对数据库中的相关表进行级联修改,强制比CHECK约束更复杂的数据完整性,并自定义错误消息,维护非规范化数据以及比较数据修改前后的状态。
与CHECK约束不同,触发器可以引用其他表中的列。在下列情况下,使用触发器将强制实现复杂的引用完整性:
强制数据库间的引用完整性
创建多行触发器当插入、更新或者删除多行数据时,必须编写一个处理多行数据的触发器
执行级联更新级联删除这样的动作
级联修改数据库中所有相关表
撤销或者回滚违反引用完整性的操作,防止非法修改数据
2.与存储过程的区别
触发器与存储过程主要的区别在于触发器的运行方式。存储过程必须由用户、应用程序或者触发器来显示式地调用并执行,而触发器是当特定事件出现的时候,自动执行或者激活的,与连接到数据库中的用户或者应用程序无关。
当一行被插入、更新或者从表中删除时触发器才运行,同时这还取决于触发器是怎样创建的。在数据修改时,触发器是强制业务规则的一种很有效的方法。一个表最多有三种不同类型的触发器,当UPDATE发生时使用一个触发器;DELETE发生时使用一个触发器;INSERT发生时使用一个触发器。
尽管触发器的功能强大,但是们也可能对服务器的性能很有害。因此,要注意不要在触发器中放置太多的功能,因为将降低响应速度,使用户等待的时间增加
42.2  触发器的分类
在SQL Server 2008系统中,按照触发事件的不同可以把提供的触发器分成两大类型:DML触发器和DDL触发器。
1.DDL触发器
DDL触发器当服务器或者数据库中发生数据定义语言(DDL)事件时将被调用。如果要执行以下操作,可以使用DDL触发器:
要防止对数据库架构进行某些更改
希望数据库中发生某种情况以响应数据库架构中的更改
要记录数据库架构中的更改或者事件
2.DML触发器
DML触发器是当数据库服务器中发生数据操作语言(DML)事件时要执行的操作。通常所说的DML触发器主要包括三种:INSERT触发器、UPDATE触发器、DELETE触发器。DML触发器可以查询其他表,还可以包含复杂的Transact-SQL语句。将触发器和触发他的语句作为可在触发器内回滚的单个事务对待。如果检测到错误,则整个事务自动回滚。
DML触发器在以下方面非常有用:
DML触发器可通过数据库中的相关表实现级联更改。不过,通过级联引用完整性约束可以更有效地进行这些更改
DML触发器可以防止恶意或者错误的INSERT、UPDATE以及DELETE操作,并强制执行比CHECK约束定义的限制更为复杂的其他限制。DML触发器能够引用其他表中的列
DML触发器可以评估数据修改前后表的状态,并根据该差异采取措施
一个表中的多个同类DML触发器(INSERT、UPDATE和DELETE)允许采取多个不同的操作来响应同一个修改语句
SQL Server 2008为每个触发器语句都创建了两种特殊的表:DELETED表和INSERTED表。这是两个逻辑表,由系统来自创建和维护,用户不能对他们进行修改。他们存放在内存而不是数据库中。这两个表的结构总是与被该触发器作用的表的结构相同。触发器执行完成后,与该触发器相关的这两个表也会被删除。
DELETE表存放由执行DELETE或者UPDATE语句而要从表中删除的所有行。在执行DELETE或者UPDATE操作时,被删除的行从触发触发器的表中被移动到DELETE表,这两
个表不会有共同的行。
INSERT表存放由执行INSERET或者UPDATE语句而要向表中插入的所有行。在执行INSERT或者UPDATE事务中,新的行同时添加到触发触发器的表和INSERT表中,INSERT表的内容是触发触发器的表中新行的副本。
一个UPDATE事务可以看作先执行一个DELETE操作,再执行一个INSERT操作,旧的行首先被移动到DELETE表,然后新行同时插入触发触发器的表和INSERT表。
42.3  触发器完整性规则
在SQL SERVER 2008中,维护数据的完整性和一致性叫完整性规则。而完整性规则分为引用完整性规则和数据完整性规则。
1.引用完整性规则
到目前为止,提供执行完整性检查的唯一方法是使用DRI(声明的引用完整性),但这不是
唯一的选项。实际上,直到6.5版本为止,DRI在以前的版本中甚至还不是一个选项,那里执行完整性检查都是用触发器来完成的。
触发器仍然是维护引用完整性的一种最好选择。虽然它们的速度有点慢,但人们认为它们在维护数据完整性上更灵活。正因如此,所以有几种关系(处理方法)只能通过触发器来执行。
使用触发器的关系的例子包括:一对一的关系、排斥关系、需要跨越数据库或服务器边界的情况。
可能不有很多类似的例子,具体有多少取决于用户的特定需要。这就是触发器的最大特点,它们具有最大的灵活性。
使用触发器维护简单的引用完整性:除了前面列出的所有技巧以外,触发器还可以用于完成DRI能完成的相同的、简单的引用完整性。一般而言,这不是我们所希望采取的方法,但有时又无法避免。其实很简单。唯一的技巧在于:只有是一对0或多对多的而不是一对多的关系,才能发生这一现象。注意,就像以前介绍的一样,我们可以用触发器为DELETE语句产生的错误创建一条定制信息。
使用触发器得到更灵活的引用完整性:以前的DRI只执行两种关系:一对一关系,或者一对零、一或多。另一个不能满足DRI常规要求的例子是排它子类关系。在这种关系中,父表拥有的消息可能与许多子表相似,但是,父表中的每行只有唯一的一条记录与子表的一条记录相匹配。对于这种关系,我们只能使用触发器作为唯一解决方案。虽然会听说使用DRI是为了获得更好的性能,但是DRI不能处理如子类这样的复杂成员。此时采用触发器可以出地完成任务。
2.数据完整性规则
触发器既能实现外部键约束的关系,也能实现如CHECK约束甚至DEFAULT约束的相同功能。像触发器与DRI一样,需要根据实现情况何时使用触发器以及何时使用使用CHECK约束。如果CHECK约束能完成该工作,或者在检查处理中继承的一些内容使得效果更不理想,就采用触发器。利用触发器替代CHECK约束的例子有:业务规则需要引用另一张的参考数据、业务规则需要检查更新的中间数据和需要一个定制的错误消息。
处理其他表的请求。虽然CHECK约束不仅快而且效率高,但它们不会按照所期望的方式完成所有工作。大概CHECK约束的最大缺点就是它要显示何时需要验证看得到表中的数据。
记住,如果愿意,也可以创建一个定制错误信息,代替使用RAISERROR命令的特殊信息。
使用触发器检查被更新的中间数据。有时,我们对过去或现在的值不感兴趣,只希望知道变化值是多少。虽然没有列或表提供这些变化信息,但我们可以利用触发器中的INSERTED表和DELETED表进行计算。
使用触发器定制错误信息。在其他一些例子中,我们已经提到了这一点,但是要记住,当希望控制错误信息或者给用户或客户应用程序传递错误号时,使用触发器非常方便。例如利用CHECK约束,我们将得到标准547号错,而不是不可名状的解释。通常,从用户实际指出发生什么错误的角度出发,这样的错误提示不会给他们提供太大的帮助,实际上,客户应用程序通常没有足够信息为用户的行为做出智能化、有帮助的响应。简而言之,虽然有时创建触发器会提供预期的数据完整性,但是它不会提供足够的处理。
42.4  创建触发器
对于不同的触发器,其创建的语法多数相似,其区别与定义表示触发器的特性有关。创建一个触发器定义的基本语法如下:
CREATE TRIGGER trigger_name
ON{ table | view }
{ {
{ FOR | AFTER | INSTEAD OF }
{ [ delete ] [,] [ insert ] [,] [ update ] }
AS
Sql_statement
} }
在DELETE TRIGGER的语法中,各主要参数含义如下:sql触发器级联删除
Trigger_name是要创建的触发器的名称。
Table| view  是在其上执行触发器的表或视图,有时称为触发器表或触发器视图。可以选择是否指定表或视图的所有者名称。
FOR,AFTER,INSTEAD OF  指定触发器触发的时机,其中FOR也创建AFTER触发器。
DELETE,INSERT,UPDATE  是指定在表或视图上执行哪些数据修改语句时将触发触发器的关键字。必须至少指定一个选项。在触发器定义中允许使用以任意顺序组合的这些关键字。如果指定的选项多于一个,需用逗号分隔这些选项。
Sql_statement指定触发器所执行的T-SQL语句。
例如,下面的语句演示了在【BookDatebase】数据库的【Books】表上创建了一个名为BooksBcountUpdate的触发器,在用户向表中执行UPDATE操作时触发。
ALTER TRIGGER [dbo].[BooksBcountUpdate]
ON [dbo].[Books]
AFTER UPDATE
AS
if UPDATE(Bcount)
BEGIN
update BookManage
set BookManage.Bcount=i.Bcount
from BookManageB,insertedi,deletedd
where B.Bnum=d.Bnum
END

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。