SQL server 触发器示例

原创 2018年02月10日 22:16:02

概念

触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。

触发器可以查询其他表,而且可以包含复杂的 SQL 语句。 它们主要用于强制服从复杂的业务规则或要求。 例如,您可以根据客户当前的帐户状态,控制是否允许插入新订单。
触发器也可用于强制引用完整性,以便在多个表中添加、更新或删除行时,保留在这些表之间所定义的关系。

作用

1)触发器可通过数据库中的相关表实现级联更改;通过级联引用完整性约束可以更有效地执行这些更改。
2)触发器可以强制比用 CHECK 约束定义的约束更为复杂的约束。与 CHECK 约束不同,触发器可以引用其它表中的列。例如,触发器可以使用另一个表中的 SELECT 比较插入或更新的数据,以及执行其它操作,如修改数据
或显示用户定义错误信息。
3)触发器还可以强制执行业务规则
4)触发器也可以评估数据修改前后的表状态,并根据其差异采取对策。

实际应用

尽管触发器有很多优点,但是在实际的项目开发中,特别是OOP思想的深入,触发器的弊端也逐渐突显,主要:

1、过多的触发器使得数据逻辑变得复杂
2、数据操作比较隐含,不易进行调整修改
3、触发器的功能逐渐在代码逻辑或事务中替代实现,更符合OO思想。

语法

CREATE TRIGGER trigger_name 
ON {table_name | view_name} 
{FOR | After | Instead of } [ insert, update,delete ]
AS           
    sql_statement  

触发器类型

SQL Server 包括两种常规类型的触发器:数据操作语言 (DML) 触发器和数据定义语言 (DDL) 触发器。 当INSERT、UPDATE 或 DELETE 语句修改指定表或视图中的数据时,可以使用 DML 触发器。 DDL 触发器激发存储过程以响应各种 DDL 语句,这些语句主要以CREATE、ALTER 和 DROP 开头。 DDL 触发器可用于管理任务,例如审核和控制数据库操作。

通常说的触发器就是DML触发器。

DML 触发器在 INSERT、UPDATE 和 DELETE 语句上操作,并且有助于在表或视图中修改数据时强制业务规则,扩展数据完整性。

在SQL Server2005后又增加了DDL触发器。

DDL 触发器将激发存储过程以响应事件。但与 DML 触发器不同的是,它们不会为响应针对表或视图的 UPDATE、INSERT 或 DELETE 语句而激发。相反,它们将为了响应各种数据定义语言 (DDL) 事件而激发。这些事件主要与以关键字 CREATE、ALTER 和 DROP 开头的 Transact-SQL 语句对应。执行 DDL 式操作的系统存储过程也可以激发 DDL 触发器。

DDL 触发器使用场合:

要防止对数据库架构进行某些更改。
希望数据库中发生某种情况以响应数据库架构中的更改。
要记录数据库架构中的更改或事件。

在这里我们只讲述DML触发器。DML触发器又分以下分类:

1、 After触发器

After触发器要求只有执行某一操作insert、update、delete之后触发器才被触发,且只能定义在表上。

 1)insert触发器

 2)update触发器

 3)delete触发器 

2、Instead of 触发器

Instead of 触发器表示并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身。既可以在表上定义instead of触发器,也可以在视图上定义。

1、触发器新增

原理:

当触发INSERT触发器时,新的数据行就会被插入到触发器表和inserted表中。inserted表是一个逻辑表,它包含了已经插入的数据行的一个副本。inserted表包含了INSERT语句中已记录的插入动作。inserted表还允许引用由初始化INSERT语句而产生的日志数据。触发器通过检查inserted表来确定是否执行触发器动作或如何执行它。inserted表中的行总是触发器表中一行或多行的副本。

场景:增加学生信息时,要校验其年龄,暂定其年龄必须大于18,否则新增失败
作用:校验约束

具体实例:

CREATE TABLE STUDENTS(
    ID INT NOT NULL PRIMARY KEY,
    NAME NVARCHAR(20) NOT NULL,
    AGE INT NOT NULL,
    CITY NVARCHAR(20) NOT NULL,
    MAJORID INT NOT NULL
)
INSERT INTO STUDENTS VALUES(1,'李四',20,'SHANGHAI',11)
INSERT INTO STUDENTS VALUES(2,'王美美',22,'SHANGHAI',10)

IF OBJECT_ID (N'TRIGER_Students_Insert', N'tr') IS NOT NULL
    DROP TRIGGER TRIGER_Students_Insert;
GO
ALTER TRIGGER TRIGGER_STUDENTS_INSERT ON STUDENTS 
    FOR INSERT
AS 
BEGIN
    declare @age int
    select @age = STUDENTS.AGE from STUDENTS INNER JOIN inserted ON STUDENTS.ID=inserted.ID
    PRINT @age
    if(@age<18)
    begin

    raiserror('学生的年龄必须大于18',16,8)
    rollback tran

    end
END

执行insert

INSERT INTO STUDENTS VALUES(3,'王美美',2,'SHANGHAI',10)

执行结果
这里写图片描述

2.触发器更新

原理:

可将UPDATE语句看成两步操作:即捕获数据前像(before image)的DELETE语句,和捕获数据后像(after image)的INSERT语句。当在定义有触发器的表上执行UPDATE语句时,原始行(前像)被移入到deleted表,更新行(后像)被移入到inserted表。

触发器检查deleted表和inserted表以及被更新的表,来确定是否更新了多行以及如何执行触发器动作。

可以使用IF UPDATE语句定义一个监视指定列的数据更新的触发器。这样,就可以让触发器容易的隔离出特定列的活动。当它检测到指定列已经更新时,触发器就会进一步执行适当的动作,例如发出错误信息指出该列不能更新,或者根据新的更新的列值执行一系列的动作语句。

场景:

专业信息ID修改,对应的学生信息中专业ID也相应进行修改

实例实现:

CREATE TABLE MAJORS(
    ID INT NOT NULL PRIMARY KEY,
    MAJORNAME NVARCHAR(20) NOT NULL
)
INSERT INTO MAJORS VALUES(11,'美学')
INSERT INTO MAJORS VALUES(10,'法学')
IF OBJECT_ID (N'TRIGGER_MAJOR_UPDATE', N'tr') IS NOT NULL
    DROP TRIGGER TRIGGER_MAJOR_UPDATE;
GO
CREATE TRIGGER TRIGGER_MAJOR_UPDATE
   ON  MAJORS
   FOR UPDATE
AS 
BEGIN
    IF UPDATE(ID)
    UPDATE STUDENTS SET MAJORID=inserted.ID FROM STUDENTS,deleted,inserted
    WHERE STUDENTS.MAJORID=deleted.ID
END

原始数据:

这里写图片描述

执行更新操作:

UPDATE MAJORS SET ID=13 WHERE ID=11

执行结果:
这里写图片描述

3、触发器删除

原理:

当触发DELETE触发器后,从受影响的表中删除的行将被放置到一个特殊的deleted表中。deleted表是一个逻辑表,它保留已被删除数据行的一个副本。deleted表还允许引用由初始化DELETE语句产生的日志数据。

使用DELETE触发器时,需要考虑以下的事项和原则:

当某行被添加到deleted表中时,它就不再存在于数据库表中;因此,deleted表和数据库表没有相同的行。
创建deleted表时,空间是从内存中分配的。deleted表总是被存储在高速缓存中。
为DELETE动作定义的触发器并不执行TRUNCATE TABLE语句,原因在于日志不记录TRUNCATE TABLE语句。
场景:学校某选修课取消。

处理逻辑:在删除课程的同时,需要删除该课程的选课信息。

示例:

CREATE TABLE STUDENTS_MAJORS(
    STUDENTID INT NOT NULL,
    COURSEID INT NOT NULL
)
INSERT INTO STUDENTS_MAJORS VALUES(1,13)
INSERT INTO STUDENTS_MAJORS VALUES(2,10)

IF OBJECT_ID (N'TRIGGER_MAJORS_DELETE', N'tr') IS NOT NULL
    DROP TRIGGER TRIGGER_MAJORS_DELETE;
GO
CREATE TRIGGER TRIGGER_MAJORS_DELETE
   ON  MAJORS
   AFTER DELETE
AS 
BEGIN

    DELETE STUDENTS_MAJORS FROM STUDENTS_MAJORS,deleted WHERE STUDENTS_MAJORS.COURSEID = deleted.ID
    DELETE STUDENTS FROM STUDENTS,deleted WHERE STUDENTS.MAJORID=deleted.ID
END

执行之前数据:
这里写图片描述

执行删除课程ID=13:

DELETE FROM MAJORS WHERE MAJORS.ID=13

执行结果:
这里写图片描述

4、Instead Of 触发器

用Instead Of触发器实现与实例3相同的功能,具体实现代码如下:

IF OBJECT_ID (N'TRIGER_MAJORS_Instead_Delete', N'tr') IS NOT NULL
    DROP TRIGGER TRIGER_MAJORS_Instead_Delete;
GO
CREATE TRIGGER TRIGER_MAJORS_Instead_Delete
ON MAJORS
Instead Of DELETE
AS
BEGIN
    declare @courseId int
    --获取要删除的课程ID
    SELECT @courseId=ID FROM deleted
    --删除选课信息
    DELETE FROM STUDENTS_MAJORS WHERE COURSEID= @courseId
    --删除课程信息
    DELETE FROM MAJORS WHERE ID=@courseId
END

执行删除:
结果和列3一样

DELETE FROM MAJORS WHERE MAJORS.ID=10
版权声明:本文为博主原创文章,未经博主允许不得转载。

sqlserver 使用触发器级联添加的代码

CREATE TRIGGER [triggername] ON [dbo].[table1] FOR INSERTASinsert into table2(column1,column2,...) s...
  • dragonbbc
  • dragonbbc
  • 2006年05月22日 18:19
  • 794

sql sever 2008 触发器的问题

CREATE TRIGGER Insert_Or_Update_Sal    BEFORE INSERT OR UPDATE ON Teacher    FOR EACH ROW    AS B...
  • hhooong
  • hhooong
  • 2015年05月14日 15:38
  • 1091

SQL Server 触发器学习总结

SQL菜鸟入门级教程之触发器     触发器简介:   触发器(trigger)是种特殊的存储过程,它的执行不是由程序调用,也不需要手动操作,它是由事件来触发,事件大家应该非常熟悉吧,比如按钮的Cli...
  • bcbobo21cn
  • bcbobo21cn
  • 2016年03月12日 12:18
  • 1758

[SQL Server] 多触发器执行问题

问题描述: 在某环境中数据表存在多个触发器,数据的增删改是标准的每个表都有的触发器,此外还存在关于校验的触发器;起因是写完触发器后,有一次同事询问说触发器不起作用了,没有提示错误,但是数据无法保存;我...
  • xiaoxu0123
  • xiaoxu0123
  • 2010年03月20日 00:13
  • 811

SQL Server 2005/2008 触发器的管理和查看

通过可视化操作来管理和查看触发器 在Microsoft SQL Server Management Studio中,选中某一数据库的某一张表时,在“对象资源管理器详细”窗口中有“触发器”项。 通过...
  • wozengcong
  • wozengcong
  • 2014年08月23日 14:26
  • 738

SQL Server 触发器的使用,实现多字段自增长

今天遇到了个数据库的问题:主键ID字段自增长,编号Number字段自增长,但是SQL Server只支持一个自增长字段,那该怎么解决呢? 这时候就要用到了SQL Server的触发器功能了,废话不多...
  • yedajiang44
  • yedajiang44
  • 2017年05月25日 21:33
  • 459

如何屏蔽sqlServer触发器

我做的程序有时涉及大批量地将其他数据源的数据合并到Sqlserver数据库,这时候想不让触发器运行,否则回非常耗时,十分容易导致超时。  特请教: 该怎么暂时屏蔽触发器呢? 如能屏蔽,如何恢复正常呢?...
  • Tercel99
  • Tercel99
  • 2008年04月10日 22:59
  • 1584

一次SQLSERVER触发器编写感悟

背景:BOSS需要我写一个工厂采集端到服务器端的数据同步触发器,数据库采用的是sqlserver2008 需求:将多台采集机的数据同步到服务器中,如果采集端数据库与服务器数据库连接失败则将数据保存到...
  • u013046841
  • u013046841
  • 2015年08月21日 02:34
  • 2982

SqlServer触发器的一个例子

先抄一点关于触发器的文字介绍: 在SQL Server里面也就是对某一个表的一定的操作,触发某种条件,从而执行的一段程序。触发器是一个特殊的存储过程。 常见的有三种:分别应用于Insert , ...
  • u013992365
  • u013992365
  • 2016年12月19日 15:39
  • 4205

[SQL SERVER系列]存储过程,游标和触发器实例[原创]

自己写的存储过程与游标结合使用的实例,与大家分享,也供自己查阅,仅供参考: --使用游标循环处理,删除重复的记录 declare @UserID int declare @U...
  • peng8477
  • peng8477
  • 2016年05月13日 10:20
  • 614
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:SQL server 触发器示例
举报原因:
原因补充:

(最多只允许输入30个字)