Sql Server 触发器
⒈是什么?
触发器是一种特殊类型的存储过程,触发器主要是通过事件进行触发被自动调用执行,而存储过程可以通过存储过程的名称被调用。
当我们对某张表进行操作(例如增删改)时会自动调用执行该表上对应的触发器。
SQL Server 中触发器可以分为两类:DML触发器和DDL触发器,其中DDL触发器它们会影响多种数据定义语言语句而激发,这些语句有create、alter、drop语句。
DML触发器分为:
1、 after触发器(之后触发)
a、 insert触发器
b、 update触发器
c、 delete触发器
2、 instead of 触发器 (之前触发)
after触发器要求只有当我们对某张表进行操作(例如增删改)时才会自动调用执行该表上对应的after触发器,且只能定义在表上。
instead of触发器并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身,既可以在表上定义instead of触发器,也可以在视图上定义。
触发器有两张特殊的表:插入表(instered表)和删除表(deleted表)。这两张是逻辑表也是虚表。系统会在内存中创建这两张表,不会存储在数据库中。且这两张表的都是只读的,只能读取数据而不能修改数据。这两张表的结果总是与被改触发器应用的表的结构相同。当触发器完成工作后,这两张表就会自动被删除。Inserted表的数据是插入或是修改后的数据,而deleted表的数据是更新前的或是删除的数据。
对表的操作 |
Inserted逻辑表 |
Deleted逻辑表 |
增加记录(insert) |
存放增加的记录 |
无 |
删除记录(delete) |
无 |
存放被删除的记录 |
修改记录(update) |
存放更新后的记录 |
存放更新前的记录 |
Update数据的时候就是先删除表记录,然后增加一条记录。这样在inserted和deleted表就都有update后的数据记录了。注意的是:触发器本身就是一个事务,所以在触发器里面可以对修改数据进行一些特殊的检查。如果不满足可以利用事务回滚,撤销操作。
⒉创建触发器
1.after触发器(之后触发)
①语法
1 create trigger tgr_name on tableName 2 with encryption --加密触发器 3 for update 4 as 5 sql 6 go
②示例
Ⅰinsert类型触发器
1 if(OBJECT_ID('tgr_users_insert','tr') is not null) 2 drop trigger tgr_users_insert 3 go 4 create trigger tgr_users_insert on users 5 for insert --插入时触发 6 as 7 declare @id int,@username varchar(20); 8 select @id = id,@username = username from inserted; --inserted虚拟表中存放了新插入的那条数据 9 select concat('新用户的Id是:',@id,',新用户的用户名是:',@username); 10 go
Ⅱdelete类型触发器
1 if(OBJECT_ID('tgr_users_delete','tr') is not null) 2 drop trigger tgr_users_delete 3 go 4 create trigger tgr_users_delete on users 5 for delete --删除时触发 6 as 7 declare @id int,@username varchar(20); 8 select @id = id,@username = username from deleted; --deleted虚拟表中存放了删除的那条数据 9 select concat('删除用户的Id是:',@id,',删除用户的用户名是:',@username); 10 go
Ⅲupdate类型触发器
1 if(OBJECT_ID('tgr_users_update','tr') is not null) 2 drop trigger tgr_users_update 3 go 4 create trigger tgr_users_update on users 5 for update --更新时触发 6 as 7 declare @id int,@oldusername varchar(20),@newusername varchar(20); 8 select @id = id,@oldusername = username from deleted; --deleted虚拟表中存放了更新前的那条数据 9 select @newusername = username from inserted; --inserted虚拟表中存放了更新后的那条数据 10 select concat('更新用户的Id是:',@id,',更新前用户名是:',@oldusername,',更新后用户名是:',@newusername); 11 go
Ⅳupdate列级触发器
1 if(OBJECT_ID('tgr_users_update_column','tr') is not null) 2 drop trigger tgr_users_update_column 3 go 4 create trigger tgr_users_update_column on users 5 for update --更新时触发 6 as 7 if(update(username)) 8 begin 9 raisError('用户名禁止修改!',16,11); 10 rollback tran; 11 end 12 go
2.instead of 触发器 (之前触发)
instead of触发器表示并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身的内容。
①语法
1 create trigger tgr_name on tableName 2 with encryption --加密触发器 3 instead of update 4 as 5 sql 6 go
②示例
Ⅰinstead of触发器
1 if(OBJECT_ID('tgr_users_insteadof','tr') is not null) 2 drop trigger tgr_users_insteadof 3 go 4 create trigger tgr_users_insteadof on users 5 instead of delete --update, insert.. 6 as 7 declare @id int,@username varchar(20); 8 select @id = id , @username = username from deleted; 9 select concat('删除用户的Id是:',@id,',删除用户的用户名是:',@username); 10 go
Ⅱ显示自定义消息raiserror
1 if (OBJECT_ID('tgr_message', 'TR') is not null) 2 drop trigger tgr_message 3 go 4 create trigger tgr_message on users 5 after insert, update 6 as 7 raisError('tgr_message触发器被触发', 16, 10); 8 go
⒊修改触发器
1 alter trigger tgr_message on users 2 after delete 3 as raisError('tgr_message触发器被触发', 16, 10); 4 go
⒋启用/禁止触发器
1 --禁用触发器 2 disable trigger tgr_message on users; 3 --启用触发器 4 enable trigger tgr_message on users;
⒌查询触发器信息
1 --查询已存在的触发器 2 select * from sys.triggers; 3 select * from sys.objects where type = 'TR'; 4 5 --查看触发器触发事件 6 select te.* from sys.trigger_events te join sys.triggers t 7 on t.object_id = te.object_id 8 where t.parent_class = 0 and t.name = 'tgr_valid_data'; 9 10 --查看创建触发器语句 11 exec sp_helptext 'tgr_message';
⒍附加
1.验证数据
1 if ((object_id('tgr_valid_data', 'TR') is not null)) 2 drop trigger tgr_valid_data 3 go 4 create trigger tgr_valid_data 5 on student 6 after insert 7 as 8 declare @age int, 9 @name varchar(20); 10 select @name = s.name, @age = s.age from inserted s; 11 if (@age < 18) 12 begin 13 raisError('插入新数据的age有问题', 16, 1); 14 rollback tran; 15 end 16 go
2.操作日志
1 if (object_id('log', 'U') is not null) 2 drop table log 3 go 4 create table log( 5 id int identity(1, 1) primary key, 6 action varchar(20), 7 createDate datetime default getDate() 8 ) 9 go 10 if (exists (select * from sys.objects where name = 'tgr_student_log')) 11 drop trigger tgr_student_log 12 go 13 create trigger tgr_student_log 14 on student 15 after insert, update, delete 16 as 17 if ((exists (select 1 from inserted)) and (exists (select 1 from deleted))) 18 begin 19 insert into log(action) values('updated'); 20 end 21 else if (exists (select 1 from inserted) and not exists (select 1 from deleted)) 22 begin 23 insert into log(action) values('inserted'); 24 end 25 else if (not exists (select 1 from inserted) and exists (select 1 from deleted)) 26 begin 27 insert into log(action) values('deleted'); 28 end 29 go
原文地址,http://www.cnblogs.com/hoojo/archive/2011/07/20/2111316.html,在原作者基础上进行简化及修改。