SqlServer 触发器 详细讲解

什么是触发器

触发器是一个在修改指定表值的数据时执行的存储过程,不同的是执行存储过程要使用EXEC语句来调用,而触发器执行不需要使用EXEC语句来调用,通过创建触发器可以保证不同表的逻辑相关数据的引用完整性或一致性。

优点

1、触发器是自动的

2、触发器可以通过数据库相关表进行层叠更改。

3、触发器可以强制限制。

触发器的作用

触发器的主要作用就是能够实现主键和外键所不能保证的复杂的参照完整性和数据的一致性,它能够对数据库中的相关表进行级联修改,能够提供比CHECK约束更复杂的数据完整性,并自定义错误。触发器的主要作用由以下几个方面。

1、强制数据库间的引用完整性。

2、级联修改数据库中所有相关表,自动触发与其他与之相关的操作。

3、跟踪变化,撤销或者回滚违法操作,防止非法修改数据。

4、返回自定义错误信息,约束无法返回信息,而触发器可以。

5、触发器可以调用更多的存储过程。

触发器分类

1、数据库操作语言触发器(Data Manipulation Language,DML)触发器。

附加在表或视图上,主要有三种INSERT触发器、UPDATE触发器、DELETE触发器

2、数据定义语言(Data Definition Language,DDL)触发器。

主要用于当前服务器或者数据库中。


创建DML触发器

首先先创建两张表

CREATE TABLE [dbo].[Stu](
	[ID] [int] IDENTITY(1,1) NOT NULL,--自增长ID
	[Name] [varchar](50) NOT NULL,--学生姓名
	[subject] [varchar](50) NOT NULL,--学科
	[credit] [decimal](18, 2) NOT NULL--单科学分
	)
GO


CREATE TABLE [dbo].[Stu_sum](
	[Name] [varchar](50) NULL,--学生姓名
	[number] [int] NULL--总学分
) 
GO

现在有一张学生单科成绩表和一个成绩汇总表

   INSERT触发器

要求插入一个学生单科成绩,并把分数汇总到Stu_sum 表中,根据学生的姓名(这里做测试没有做其他约束)


CREATE TRIGGER dbo.stu_TRIGGER_INSERT
   ON dbo.Stu
   AFTER  INSERT
AS 
BEGIN
	SET NOCOUNT ON;--不返回影响行数
	--插入数据时会产生INSERTED表(表结构和Stu一样)
	--把[Stu_sum]存在的数据先更新掉
	update b set b.number=isnull(b.number,0)+a.credit from 
	(select [Name],sum(credit) credit  from  INSERTED group by [Name]) a
	join [dbo].[Stu_sum] b on a.Name=b.Name
	--把不存在的添加进[Stu_sum]
	INSERT into [dbo].[Stu_sum](Name,number)
	select a.Name,a.credit
	 from 
	(select [Name],sum(credit) credit  from  INSERTED group by [Name]) a
	left join [dbo].[Stu_sum] b on a.Name=b.Name
	where b.Name is null
END
GO

首先插入一条数据

insert into [dbo].[Stu]([Name],[subject],[credit]) values('张三','数学',100),('张三','英语',100)

查询结果,如下图Stu_Sum表中

select * from [Stu]
select * from [Stu_sum]

DELETE触发器

先插入几条值

insert into [dbo].[Stu]([Name],[subject],[credit]) values('张三','体育',60),('李四','英语',100),('李四','语文',80)

先查询一下表看一下表目前的值

目标删除张三的体育成绩,同时更新张三的总成绩。

DELETE触发器创建

CREATE TRIGGER dbo.stu_TRIGGER_DELETE
   ON dbo.Stu
   AFTER  DELETE
AS 
BEGIN
	SET NOCOUNT ON;--不返回影响行数
	--删除数据时会产生DELETEED表(表结构和Stu一样)
	--把[Stu_sum]存在的数据更新掉
	update b set b.number=isnull(b.number,0)-a.credit from 
	(select [Name],sum(credit) credit  from  DELETED group by [Name]) a
	join [dbo].[Stu_sum] b on a.Name=b.Name
END
GO

执行删除语句

delete from [dbo].[Stu] where Name='张三' and subject='体育'

查看结果

UPDATE触发器

案例:需要把张三数学改成98分,同时修改张三总成绩

创建UPDATE触发器

CREATE TRIGGER dbo.stu_TRIGGER_UPDATE
   ON dbo.Stu
   AFTER  UPDATE
AS 
BEGIN
	SET NOCOUNT ON;--不返回影响行数
	--更新数据时会产生INSERTED 、DELETEED表(表结构和Stu一样)
	--把[Stu_sum]存在的数据更新掉
	update b set b.number=isnull(b.number,0)+d.credit from 
	(select Name,sum(credit) credit from
	(select a.[Name],b.credit-a.credit credit  from  DELETED a join INSERTED b on a.ID=b.ID) c group by [name]) d
	join [dbo].[Stu_sum] b on d.Name=b.Name
END
GO

执行语句

update [dbo].[Stu] set [credit]=98 where [Name]='张三' and [subject]='数学'

查看结果

替代触发器

与前面介绍了三种AFTER触发器不同,SQLServer 服务器在执行触发AFTER触发器的SQL代码后,先建立临时的INSERTED和DELETED表,然后执行SQL代码中对数据的操作,最后才激活触发器中的代码。而对于替代(INSTEAD OF)触发器,SQL SERVER服务器执行触发INSERTAD OF 触发器时,先建立临时的INSERTED和DELETED表,然后直接触发INSTEAD OF 触发器。

案例:当用户插入学生单科成绩大于100分时,直接提示报错。

创建触发器


CREATE TRIGGER dbo.stu_TRIGGER_INSTEADOF
   ON dbo.Stu
   INstead of  INSERT
AS 
BEGIN
	if exists(select ID from inserted where credit>100)
	begin
		select '插入成绩错误' as 错误原因
	end
END
GO

执行插入语句

insert into [dbo].[Stu]([Name],[subject],[credit]) values('张三','体育',130)

执行结果,错误的成绩没有被插入。

猜你喜欢

转载自blog.csdn.net/lovezhai/article/details/107592503