trigger 专题
2008-01-24 09:05
113 查看
触发器功能强大,轻松可靠地实现许多复杂的功能,为什么又要慎用呢。 触发器本身没有过错,但由于我们的滥用会造成数据库及应用程序的维护困难。
在数据库操作中,我们可以通过关系、触发器、存储过程、应用程序等来实现数据操作,比如删除 T1 表记录时期望删除 T2 表相关的记录,此时可以建立级联删除的关系,也可以为 T1 表建立触发器使同时删除 T2 表相关记录,也可以自定义存储过程删除 T1 和 T2 表的记录,也可以在应用程序中使用两个 SQL 语句来删除……到底用哪一种好呢,应该说我们建立通过建立关系来实现级联删除是最好的,除非更有高的需求。
触发器还有一个用途可以用来保障数据的完整性,但同时规则、约束、默认值也可以保障数据完整性,到底哪一个好呢,一般说来,较为简单的完整性要求我们不应该使用触发器。两者在运行机制上也是有区别的,像规则、约束、默认值这些是在数据更改之前进行数据验证,而触发器是在数据更改之后进行验证(如果事务回滚,该表将不会产生变化)。
总之,如果我们对触发器过分的依赖,就会造成遍地是程序的情况,因为触发器本身就需要别的程序给它一个触发条件,也就是说至少在两个地方存在着程序,同时我们抛弃了约束、默认值等而选用触发器,势必影响数据库的结构。
触发器是一种特殊的存储过程,类似于事件函数,SQL Server™ 允许为 INSERT、UPDATE、DELETE 创建触发器,即当在表中插入、更新、删除记录时,触发一个或一系列 T-SQL语句。
触发器可以在查询分析器里创建,也可以在表名上点右键->“所有任务”->“管理触发器”来创建,不过都是要写 T-SQL 语句的,只是在查询分析器里要先确定当前操作的数据库。
创建触发器用 CREATE TRIGGER
CREATE TRIGGER 触发器名称
ON 表名
FOR INSERT、UPDATE 或 DELETE
AS
T-SQL 语句
注意:触发器名称是不加引号的。
如下是联机丛书上的一个示例,当在 titles 表上更改记录时,发送邮件通知 MaryM。
CREATE TRIGGER reminder
ON titles
FOR INSERT, UPDATE, DELETE
AS
EXEC master..xp_sendmail 'MaryM',
'Don''t forget to print a report for the distributors.'
用查询分析器删除
在查询分析器中使用 drop trigger 触发器名称 来删除触发器。
也可以同时删除多个触发器:drop trigger 触发器名称,触发器名称...
注意:触发器名称是不加引号的。在删除触发器之前可以先看一下触发器是否存在:
if Exists(select name from sysobjects where name=触发器名称 and xtype='TR')
用企业管理器删除
在企业管理器中,在表上点右键->“所有任务”->“管理触发器”,选中所要删除的触发器,然后点击“删除”。
递归触发器
递归分两种,间接递归和直接递归。我们举例解释如下,假如有表1、表2名称分别为 T1、T2,在 T1、T2 上分别有触发器 G1、G2。
间接递归:对 T1 操作从而触发 G1,G1 对 T2 操作从而触发 G2,G2 对 T1 操作从而再次触发 G1...
直接递归:对 T1 操作从而触发 G1,G1 对 T1 操作从而再次触发 G1...
嵌套触发器
类似于间接递归,间接递归必然要形成一个环,而嵌套触发器不一定要形成一个环,它可以 T1->T2->T3...这样一直触发下去,最多允许嵌套 32 层。
设置直接递归
默认情况下是禁止直接递归的,要设置为允许有两种方法:
T-SQL:exec sp_dboption 'dbName', 'recursive triggers', true
EM:数据库上点右键->属性->选项。
设置间接递归、嵌套
默认情况下是允许间接递归、嵌套的,要设置为禁止有两种方法:
T-SQL:exec sp_configure 'nested triggers', 0 --第二个参数为 1 则为允许
EM:注册上点右键->属性->服务器设置。
触发器到底可不可以在视图上创建 在 SQL Server™ 联机丛书中,是没有说触发器不能在视图上创建的, 并且在语法解释中表明:在 CREATE TRIGGER 的 ON 之后可以是视图。 然而,事实似乎并不是如此,很多专家也说触发器不能在视图上创建。 我也专门作了测试,的确如此,不管是普通视图还是索引视图,都无法在上面创建触发器,真的是这样吗?
在视图上创建普通触发器可能会出现“对象无效”的错误,实际上,我们不能在视图上创建 FOR 触发器,而应该创建 INSTEAD OF 触发器
INSTEAD OF
执行触发器语句,但不执行触发触发器的 SQL 语句,比如试图删除一条记录时,将执行触发器指定的语句,此时不再执行 delete 语句。例:
create trigger f
on tbl
instead of delete
as
insert into Logs...
IF UPDATE(列名)
检查是否更新了某一列,用于 insert 或 update,不能用于 delete。例:
create trigger f
on tbl
for update
as
if update(status) or update(title)
sql_statement --更新了 status 或 title 列
inserted、deleted
这是两个虚拟表,inserted 保存的是 insert 或 update 之后所影响的记录形成的表,deleted 保存的是 delete 或 update 之前所影响的记录形成的表。例:
create trigger tbl_delete
on tbl
for delete
as
declare @title varchar(200)
select @title=title from deleted
insert into Logs(logContent) values('删除了 title 为:' + title + '的记录')
说明:如果向 inserted 或 deleted 虚拟表中取字段类型为 text、image 的字段值时,所取得的值将会是 null。
不能在触发器中使用的语句 触发器中可以使用大多数 T-SQL 语句,但如下一些语句是不能在触发器中使用的。
CREATE 语句,如:CREATE DATABASE、CREATE TABLE、CREATE INDEX 等。
ALTER 语句,如:ALTER DATABASE、ALTER TABLE、ALTER INDEX 等。
DROP 语句,如:DROP DATABASE、DROP TABLE、DROP INDEX 等。
DISK 语句,如:DISK INIT、DISK RESIZE。
LOAD 语句,如:LOAD DATABASE、LOAD LOG。
RESTORE 语句,如:RESTORE DATABASE、RESTORE LOG。
RECONFIGURE
说明:有人说不能用 TRUNCATE TABLE 语句,其实是可以的
在数据库操作中,我们可以通过关系、触发器、存储过程、应用程序等来实现数据操作,比如删除 T1 表记录时期望删除 T2 表相关的记录,此时可以建立级联删除的关系,也可以为 T1 表建立触发器使同时删除 T2 表相关记录,也可以自定义存储过程删除 T1 和 T2 表的记录,也可以在应用程序中使用两个 SQL 语句来删除……到底用哪一种好呢,应该说我们建立通过建立关系来实现级联删除是最好的,除非更有高的需求。
触发器还有一个用途可以用来保障数据的完整性,但同时规则、约束、默认值也可以保障数据完整性,到底哪一个好呢,一般说来,较为简单的完整性要求我们不应该使用触发器。两者在运行机制上也是有区别的,像规则、约束、默认值这些是在数据更改之前进行数据验证,而触发器是在数据更改之后进行验证(如果事务回滚,该表将不会产生变化)。
总之,如果我们对触发器过分的依赖,就会造成遍地是程序的情况,因为触发器本身就需要别的程序给它一个触发条件,也就是说至少在两个地方存在着程序,同时我们抛弃了约束、默认值等而选用触发器,势必影响数据库的结构。
触发器是一种特殊的存储过程,类似于事件函数,SQL Server™ 允许为 INSERT、UPDATE、DELETE 创建触发器,即当在表中插入、更新、删除记录时,触发一个或一系列 T-SQL语句。
触发器可以在查询分析器里创建,也可以在表名上点右键->“所有任务”->“管理触发器”来创建,不过都是要写 T-SQL 语句的,只是在查询分析器里要先确定当前操作的数据库。
创建触发器用 CREATE TRIGGER
CREATE TRIGGER 触发器名称
ON 表名
FOR INSERT、UPDATE 或 DELETE
AS
T-SQL 语句
注意:触发器名称是不加引号的。
如下是联机丛书上的一个示例,当在 titles 表上更改记录时,发送邮件通知 MaryM。
CREATE TRIGGER reminder
ON titles
FOR INSERT, UPDATE, DELETE
AS
EXEC master..xp_sendmail 'MaryM',
'Don''t forget to print a report for the distributors.'
用查询分析器删除
在查询分析器中使用 drop trigger 触发器名称 来删除触发器。
也可以同时删除多个触发器:drop trigger 触发器名称,触发器名称...
注意:触发器名称是不加引号的。在删除触发器之前可以先看一下触发器是否存在:
if Exists(select name from sysobjects where name=触发器名称 and xtype='TR')
用企业管理器删除
在企业管理器中,在表上点右键->“所有任务”->“管理触发器”,选中所要删除的触发器,然后点击“删除”。
递归触发器
递归分两种,间接递归和直接递归。我们举例解释如下,假如有表1、表2名称分别为 T1、T2,在 T1、T2 上分别有触发器 G1、G2。
间接递归:对 T1 操作从而触发 G1,G1 对 T2 操作从而触发 G2,G2 对 T1 操作从而再次触发 G1...
直接递归:对 T1 操作从而触发 G1,G1 对 T1 操作从而再次触发 G1...
嵌套触发器
类似于间接递归,间接递归必然要形成一个环,而嵌套触发器不一定要形成一个环,它可以 T1->T2->T3...这样一直触发下去,最多允许嵌套 32 层。
设置直接递归
默认情况下是禁止直接递归的,要设置为允许有两种方法:
T-SQL:exec sp_dboption 'dbName', 'recursive triggers', true
EM:数据库上点右键->属性->选项。
设置间接递归、嵌套
默认情况下是允许间接递归、嵌套的,要设置为禁止有两种方法:
T-SQL:exec sp_configure 'nested triggers', 0 --第二个参数为 1 则为允许
EM:注册上点右键->属性->服务器设置。
触发器到底可不可以在视图上创建 在 SQL Server™ 联机丛书中,是没有说触发器不能在视图上创建的, 并且在语法解释中表明:在 CREATE TRIGGER 的 ON 之后可以是视图。 然而,事实似乎并不是如此,很多专家也说触发器不能在视图上创建。 我也专门作了测试,的确如此,不管是普通视图还是索引视图,都无法在上面创建触发器,真的是这样吗?
在视图上创建普通触发器可能会出现“对象无效”的错误,实际上,我们不能在视图上创建 FOR 触发器,而应该创建 INSTEAD OF 触发器
INSTEAD OF
执行触发器语句,但不执行触发触发器的 SQL 语句,比如试图删除一条记录时,将执行触发器指定的语句,此时不再执行 delete 语句。例:
create trigger f
on tbl
instead of delete
as
insert into Logs...
IF UPDATE(列名)
检查是否更新了某一列,用于 insert 或 update,不能用于 delete。例:
create trigger f
on tbl
for update
as
if update(status) or update(title)
sql_statement --更新了 status 或 title 列
inserted、deleted
这是两个虚拟表,inserted 保存的是 insert 或 update 之后所影响的记录形成的表,deleted 保存的是 delete 或 update 之前所影响的记录形成的表。例:
create trigger tbl_delete
on tbl
for delete
as
declare @title varchar(200)
select @title=title from deleted
insert into Logs(logContent) values('删除了 title 为:' + title + '的记录')
说明:如果向 inserted 或 deleted 虚拟表中取字段类型为 text、image 的字段值时,所取得的值将会是 null。
不能在触发器中使用的语句 触发器中可以使用大多数 T-SQL 语句,但如下一些语句是不能在触发器中使用的。
CREATE 语句,如:CREATE DATABASE、CREATE TABLE、CREATE INDEX 等。
ALTER 语句,如:ALTER DATABASE、ALTER TABLE、ALTER INDEX 等。
DROP 语句,如:DROP DATABASE、DROP TABLE、DROP INDEX 等。
DISK 语句,如:DISK INIT、DISK RESIZE。
LOAD 语句,如:LOAD DATABASE、LOAD LOG。
RESTORE 语句,如:RESTORE DATABASE、RESTORE LOG。
RECONFIGURE
说明:有人说不能用 TRUNCATE TABLE 语句,其实是可以的
相关文章推荐
- /proc/sysrq-trigger的使用
- [kuangbin带你飞]专题八 生成树 F
- 面向对象系统分析与开发专题<2>__面向对象方法与工具
- java数据结构链表,堆栈,队列等相关专题分析与扯谈-队列
- Java报表软件定时器日报专题
- 搜索专题训练hdu2510符号三角形
- 监控登陆数据库的trigger
- jzoj P1029【NOIP动态规划专题】电子眼
- Oracle 过程(Procedure)、函数(Function)、包(Package)、触发器(Trigger)
- 【redis专题(1)】安装与启动
- SAP屏幕设计器专题:拖拉控件的强大(一)
- 【算法系列学习】Dijkstra算法变形 [kuangbin带你飞]专题四 最短路练习
- ASP.NET 4.0 专题实务(II) – 范例应用与4.0新功能(VB / C#双语法)的「勘误表」
- [kuangbin带你飞]专题七 线段树 题解(未完)
- 专题笔记--Java 类集框架
- 【redis专题(4)】命令语法介绍之sorted_set
- [MVVM专题]__神马是MVVM
- webpack多页应用架构专题系列-一套配置吃天下
- 【图像算法】彩色图像分割专题四:测试图片的生成
- dp专题 第三题 采药