定义

触发器【trigger】是一种特殊的存储过程,它在表的数据变化时发生作用。触发器可以维护数据完整性
触发器的作用就是保证参照完整性和数据的一致性
在这里插入图片描述
在这里插入图片描述

重点 实际开发经常用

在这里插入图片描述
在这里插入图片描述ML触发器分为:
1、after触发器(之后触发)
a、insert触发器
b、update触发器
c、delete触发器
2、instead of触发器(之前触发)
after触发器要求只有执行某一操作(insert、update、delete)之后触发器才能被触发,且只能定义在表上。
而instead of触发器表示并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身,其优先级高于触发语句的执行。

创建触发器 语法

     CREATE TRIGGER trigger_name
     ON table_name | View_name 
     [WITH ENCRYPTION]
     FOR [DELETE, INSERT, UPDATE] | instead of [DELETE, INSERT, UPDATE] 
     [NO FOR REPLICATION]
     AS
	    [ { IF UPDATE ( column )
	  [ { AND | OR } UPDATE ( column ) ]
	  [ …n ]
	  | IF ( COLUMNS_UPDATED ( ) updated_bitmask )
	  column_bitmask [ …n ]
	  } ]
       T-SQL语句
     GO
FOR: 表示为AFTER触发器,且触发器**仅能在表上创建**
INSTEASD OF:指定触发器为INSTEAD OF触发器
deleteinsertupdate:指明执行那种操作,将激活触发器,至少要包含3种操作类型的一种,也可以是3种操作语句的任意组合。其中三者的顺序不受限制,且各选项要用逗号隔开
NO FOR REPLICATION:告诉DMBMS,当复制表时,触发器不能被执行
IF UPDATE  column :用来测定对某一确定列是insert操作haisupdate操作,如果要测试insert还是update操作的列多于一列,可用andor 逻辑连接向if update 子句添加所希望的附加列名
IF  COLUMNS_UPDATED ( ):仅在insertupdate类型的触发器中使用,检查列是被更新还是被插入
IF UPDATED(column)判断一个字段是否更新,IF COLUMNS_updated可以判断多个字段

在这里插入图片描述

在这里插入图片描述

注意事项

每个表最多只能有一个INSTEAD OF(insert 、update、delete)触发器,然而可以为每个表创建多个视图,对每个视图都可以有不同的 instead of 触发器

删除触发器

DROP TRIGGER trigger_name[,n]

Case 1 Insert 触发器

说明:为STUDENT表触发器S_insert,当向STUDENT表中插入数据时,要求学号必须以‘99’开头,且课程号CNO必须在COURSE表中,否则取消插入操作。代码如下:

create trigger s_insert
on STUDENT
for insert 
as
declare @s_no varchar(4),@s_cno int
select @s_no=SNO,@s_cno=CNO from inserted
if (left(@s_no,2)!='99')
begin
	ROLLBACK TRANSACTION
	RAISERROR('输入的学号:%s不是99级的学生,请确认后重新录入!',16,1,@s_no)
end
if (@s_cno not in (select cno from COURSE))
begin
	ROLLBACK TRANSACTION
	RAISERROR('输入的课程号:%d在COURSE表中不存在,请确认后重新录入!',16,1,@s_cno)
end

注意

可用在一个表上创建多个触发器,数据库把一个表中所有触发器都看作同一个事物的一部分。因此只要其中一个触发器执行了ROLLBACK TRANSACTION语句,那么所有的操作(与该insert语句有关)都将取消

case 2 delete 触发器
CREATE TRIGGER S_delete 
ON STUDENT 
	FOR delete
AS 
declare @rowcount int
select @rowcount=@@ROWCOUNT
if @rowcount>1
 begin
  ROLLBACK TRANSACTION
  RAISERROR('当前要删除的记录数为%d,一次只允许删除一行记录',16,1,@rowcount)
 end
declare @S_dname varchar(16),@S_cno int
select @S_dname=DNAME, @S_cno=CNO from deleted
if(@S_cno in (select CNO from Teacher where DNAME=@S_dname))
BEGIN
  
   ROLLBACK TRANSACTION
   raiserror('删除记录的课程为本系即%s系教师所开设,不允删除!',16,1,@S_cno)
END
GO

注意

在SQL server 、mysql 中执行  TRUNCATE TABLE 语句,从表中删除所有的行时,不会触发DELETE触发器

case 3 update 触发器

特定的表上执行update 语句时,会触发update触发器。update 操作包括两个部分:
1、先及那个需要更新的内容从表中删除 deleted
2、然后插入新值 inserted
因此update触发器同时涉及到删除表和插入表

为了COURSE表创建update触发器C_update,当course表的CNO和CNAME (第1列和第2列)被更新时,触发器给出提示信息,该两列不能被更新,并回滚事物。其余的列(第3、4、5列)被更新时,触发器将更新前后的数据写入C_Upinfo表中。代码如下:

---创建跟踪信息表C_UpInfo
create table C_UpInfo
(
	Opre_Time smalldatetime,
	Date_Type CHAR(3).
	CNO int,
	CNAME char(30),
	CTIME int,
	SCOUNT int,
	CTEST smalldatetime
)

-----创建UPDATE触发器 C_update
create trigger C_update
on COURSE
for UPDATE 
as
if (COLUMNS_UPDATE()&>3)   ---第1列或第二列被更新 11  转换10进制 3   &  指定多列中某一列更新   =  指定多列全部更新    
	begin
		ROLLBACK TRANSACTION 
		RAISERROR('COURSE表的CNO和CNAME列中的数据不允许被更新!',16,1)
	end
if (COLUMNS_UPDATE()&28>0)---第3或4或5被更新   00111  再从右到左 11100   转换十进制 28
	begin
		--将DELETED表【存放COURSE旧的数据】中存放的记录即更新前的记录存如UpInfo 表
		insert into UpInfo(Oper_Time,Date_Type,CNO,CNAME,CTIME,SCOUNT,CTEST)
		select GETDATE(),'OLD',del.CNO,del.CNAME,del.CTIME,del.SCOUNT,del.CTEST from deleted as del
		---将inserted 表中存放的记录,即更新后的记录存入UpInfo
		insert into UpInfo(Oper_Time,Date_Type,CNO,CNAME,CTIME,SCOUNT,CTEST)
		select GETDATE(),'NEW',ins.CNO,ins.CNAME,ins.CTIME,ins.SCOUNT,ins.CTEST from inserted as ins
	end

INSTEAD OF 触发器

INSTEAD OF 触发器的优点是使不能被更新给的视图支持更新操作。为了提高查询性能,视图通常来自多个表的结果集,基于多表视图不能被更新,而通过INSTEAD OF 触发器则可用实现这个功能,
在这里插入图片描述

---创建表 Stu97、Stu98、Stu99 
create table Stu97
(
	Sno char(5),
	Sname Char(8),
	Age int
)
create table Stu97
(
	Sno char(5),
	Sname Char(8),
	Age int
)
create table Stu97
(
	Sno char(5),
	Sname Char(8),
	Age int
)
---------创建视图Stu_View
create view Stu_View
as
select *  from Stu97
union all
select *  from Stu98
union all
select *  from Stu99

----为视图Stu_View 创建INSTEAD OF 触发器 Stu_Instead
create trigger Stu_Instead
on Stu_View
INSTEAD OF INSERT 
as
begin
	declare @S_NO char(2)
	--该变量用于存放插入数据的学号Sno的前2位,以判断插入记录属于哪张表
	select @S_NO=substring(SNO,2) from inserted
	if @S_NO-'97' --由学号判断该学生属于97级学生,记录插入Stu97表
		begin
			insert into Stu97 select  Sno,Sname,Age from INSERTED 
			return 
		end
	if @S_NO-'98' --由学号判断该学生属于97级学生,记录插入Stu98表
		begin
			insert into Stu97 select  Sno,Sname,Age from INSERTED 
			return 
		end
	if @S_NO-'99' --由学号判断该学生属于97级学生,记录插入Stu99表
		begin
			insert into Stu97 select  Sno,Sname,Age from INSERTED 
			return 
		end
	else
		begin
			ROLLBACK TRANSACTION
			RAISERROR('插入记录的学号信息不正确,请确认97级、98级、99级学生的学号!',16,1)
		end
		
end

嵌套触发器

当某一触发器执行时,能够触发另外一个触发器,这种情况称之触发器嵌套。在执行过程中,如果一个触发器修改某个表,而这个表已经有其它触发器,这时就使用了嵌套触发器。在SQL SERVER中,触发器嵌套至32层。如果不需要嵌套触发器,可以通过sp_configure 选项来进行设置

Oracle 数据库不支持嵌套触发器
案例
create trigger A_delete
on Author
for delete
as
declare @rowcount int
select @rowcount=@@ROWCOUNT 
----记录删除操作所涉及的行数
if @rowcount>1
	begin
		ROLLBACK TRANSACTION
		RAISERROR('当前要删除的记录数%d,一次只允许删除一行记录!',16,1,@rowcount)
	end
else
	begin
		declare @Author char(8)
		select @Author=Author from deleted ---记录删除记录的Author列信息
		
		Delete Book where Author=@Author
	end


----为Book表创建 delete 触发器 B_delete
create trigger  B_delete
on Book
for delete
as
declare @rowcount int
select @rowcount=@@ROWCOUNT
if @rowcount>1
	begin
		ROLLBACK TRANSACTION
		RAISERROR('当前要删除的记录数为%d,一次只允许删除一行记录!',16,1,@rowcount)
	end
else
	print 'Author表和Book表中相应的数据均被删除'

递归触发器

即由 trigger1 触发 trigger2, trigger2 又可用触发 trigger3,。。。。,而如果触发器triggern又触发trigger1,这就形成了递归触发器。

递归触发器分两种
1、间接递归
2、直接递归
假如有表Table1 、 Table2,在Table1、Table2上分别有触发器Trigger1、Trigger2

  1. 间接递归 对Table1操作触发Trigger1,Trigger1对Table2操作从而触发Trigger2,Trigger2对Table1操作从而再次触发Trigger1,。。。。
  2. 间接递归 对Table1操作从而触发Trigger1,Trigger1对Table1操作从而再次触发Trigger1,。。。。
注意

在默认情况下,SQL SERVER 是禁止直接递归的,要使SQL SERVER支持直接递归,可采用如下两种方式进行设置

1、通过系统存储过程sp_dboption 进行设置

语法:
sp_dboption ‘dbname’,‘Recursive Triggers’,true
dbname:数据库
False:则禁止数据库直接递归

2、通Enterprise Manager进行设置

在这里插入图片描述

在这里插入图片描述
查看触发器
1、sp_help
2、sp_helptext 查看表、视图、存储过程、触发器等以文本信息展现,即触发器的创建语句。
3、sp_depends 能够查看指定触发器所引用的表或指定的表涉及到的所有触发器
sp_depends Table1 — 查看Table1表涉及到的所有触发器

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐