触发器
触发器是一种特殊类型的存储过程,它在您使用一种或多种数据修改操作(UPDATE、INSERT 或 DELETE)来修改指定表中的数据时运行。
触发器分类
DML触发器和DDL触发器,其中
DML触发器分为:
1、 after触发器(之后触发)
a、 insert触发器
b、 update触发器
c、 delete触发器
2、 instead of 触发器 (之前触发)
数据操作与逻辑表间关系
| 新增 | 更新 | 删除 |
inserted(后) | √ | √ |
|
deleted(前) |
| √ | √ |
以下实例可以体现上述关系(代码来自:):
if (object_id('log', 'U') is not null) drop table loggocreate table log( id int identity(1, 1) primary key, action varchar(20), createDate datetime default getDate())goif (exists (select * from sys.objects where name = 'tgr_student_log')) drop trigger tgr_student_loggocreate trigger tgr_student_logon studentafter insert, update, deleteas if ((exists (select 1 from inserted)) and (exists (select 1 from deleted))) begin insert into log(action) values('updated'); end else if (exists (select 1 from inserted) and not exists (select 1 from deleted)) begin insert into log(action) values('inserted'); end else if (not exists (select 1 from inserted) and exists (select 1 from deleted)) begin insert into log(action) values('deleted'); endgo--testinsert into student values('king', 22, 1, 7);update student set sex = 0 where name = 'king';delete student where name = 'king';select * from log;select * from student order by id;
注:Update数据的时候就是先删除表记录,然后增加一条记录。这样在inserted和deleted表就都有update后的数据记录了。注意的是:触发器本身就是一个事务,所以在触发器里面可以对修改数据进行一些特殊的检查。如果不满足可以利用事务回滚,撤销操作。
查询创建的触发器信息
--查询已存在的触发器select * from sys.triggers;select * from sys.objects where type = 'TR';--查看触发器触发事件select te.* from sys.trigger_events te join sys.triggers ton t.object_id = te.object_idwhere t.parent_class = 0 and t.name = 'tgr_valid_data';--查看创建触发器语句exec sp_helptext 'tgr_message';
启用、禁用触发器
--禁用触发器disable trigger tgr_message on student;
alter table student disable trigger tgr_message
--启用触发器 enable trigger tgr_message on student;
alter table student enable trigger tgr_message --禁用某个表上的所有触发器 ALTER TABLE 你的表 DISABLE TRIGGER all --启用某个表上的所有触发器 ALTER TABLE 你的表 enable TRIGGER all --禁用所有表上的所有触发器 exec sp_msforeachtable 'ALTER TABLE ? DISABLE TRIGGER all' --启用所有表上的所有触发器 exec sp_msforeachtable 'ALTER TABLE ? enable TRIGGER all'
事务回滚,撤销操作
if ((object_id('tgr_valid_data', 'TR') is not null)) drop trigger tgr_valid_datagocreate trigger tgr_valid_dataon studentafter insertas declare @age int, @name varchar(20); select @name = s.name, @age = s.age from inserted s; if (@age < 18) begin raisError('插入新数据的age有问题', 16, 1); rollback tran; endgo--testinsert into student values('forest', 2, 0, 7);insert into student values('forest', 22, 0, 7);select * from student order by id;
创建instead of触发器
instead of触发器表示并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身的内容。
比如删除主表数据之前要先删除从表的时候,可以在主表建立instead of delte触发器。
if (object_id('tgr_classes_inteadOf', 'TR') is not null) drop trigger tgr_classes_inteadOfgocreate trigger tgr_classes_inteadOfon classes instead of delete/*, update, insert*/as declare @id int, @name varchar(20); --查询被删除的信息,病赋值 select @id = id, @name = name from deleted; print 'id: ' + convert(varchar, @id) + ', name: ' + @name; --先删除student的信息 delete student where cid = @id; --再删除classes的信息 delete classes where id = @id; print '删除[ id: ' + convert(varchar, @id) + ', name: ' + @name + ' ] 的信息成功!';go
以上整理大部分剽窃自: