2008从入门到了然,触发器入门

目录

触发器

概念:

开卷目录

  • 1.触发器
    • 1.1.DDL触发器
    • 1.2.DML触发器
    • 1.3.创立触发器
      • 1.3.1.创建DML触发器
      • 1.3.2.创建DDL触发器
      • 1.3.3.嵌套触发器
      • 1.3.4.递归触发器
    • 1.4.管制触发器

        触发器简介:

  触发器(trigger)是SQL server 提供给程序员和数码分析员来保证数据完整性的一种艺术,它是与表事件相关的特种的贮存过程,它的履行不是由程序调用,也不是手工启动,而是由事件来触发,当对一个表展开操作( insert,delete, update)时就会激活它实施。触发器平常用来加强数据的完整性约束和事情规则等。 触发器可以从 DBA_TRIGGERS ,USER_TRIGGERS 数据字典中查到。

  • 一:触发器的长处
  • 二:触发器的效用
  • 三:触发器的归类
  • 四:触发器的做事原理
  • 五:创制触发器
  • 六:管理触发器 

1.触发器

触发器是一种特其余仓储过程,与表紧密关系。

 
       

触发器(trigger)是个例外的蕴藏过程,它的进行不是由程序调用,也不是手工启动,而是由事件来触发,当对一个表展开操作( 
insert,delete,
update)时就会激活它实施,触发器经常用来加强数据的完整性约束和事情规则等。在我看来触发器实际上就是一个事变,就像C#中,点击一个按钮会触发相应的操作。

触发器和存储过程的界别:

概念:

1.1.DDL触发器

当服务器或数据库中爆发多少定义语言(DDL)事件时将被调用。如CREATE,ALTERDROP等操作。如若要执行以下操作,可以利用DDL触发器:

  • 预防对数据库架构举办变更
  • 愿意数据库中暴发一些情形以响应数据库架构中的更改
  • 要记录数据库架构中的更改或事件

        触发器的归类:

  触发器与存储过程的区别是运作模式的不同,触发器无法执行EXECUTE语句调用,而是在用户执行Transact-SQL语句时自动触发执行而存储过程需要用户,应用程序或者触发器来显示地调用并推行。

  触发器(trigger)是SQL server 提供给程序员和数量分析员来保证数据完整性的一种方法,它是与表事件相关的独特的囤积过程,它的施行不是由程序调用,也不是手工启动,而是由事件来触发,当对一个表举行操作( insert,delete, update)时就会激活它实施。触发器平日用来加强数据的完整性约束和作业规则等。 触发器可以从 DBA_TRIGGERS ,USER_TRIGGERS 数据字典中查到。

1.2.DML触发器

当数据库服务器中生出多少操作语言(DML)事件时将被调用。如INSERT,DELETE,UPDATE等操作。将DML触发器和触发语句作为可在触发器内回滚的单个事务对待,假如检测到不当,则整个业务回滚。DML触发器在转瞬方面充分管用:

  • 可实现数据库相关表之间的级联更改
  • 可以防范恶意或不当的DML话语事件,并强制执行比CHECK封锁越来越复杂的其它限制
  • 可以评估数据修改前后表的情况,并依照该差别接纳措施

一个表中的几个同类DML触发器,允许用两个例外的操作来响应同一个改动语句
SQL Server
2008
为每个触发器制造了2个与众不同的表:INSERTED表和DELETED表。这是六个逻辑表,由系统来创制和维护,用户不可以对他们举办修改。它们存放在内存中,而不是在数据库中,并且社团与被DML触发器功用的表的结构同样。
INSERTED表中存放了由履行INSERTUPDATE语句而插入的持有行,在推行INSERTUPDATE讲话时,新的就要同时被插入到触发器功效的表和INSERTED表中。INSERTED表中的行是触发器效能的表中行的副本。
DELETED表中存放了由履行DELETEUPDATE语句而除去的具有行,在执行DELETEUPDATE2008从入门到了然,触发器入门。说话时,被剔除的就要由触发器成效的表中被挪动到DELETED表,六个表中不会有重复行。

        (1)DML( 数据操纵语言 Data Manipulation Language)触发器:是指触发器在数据库中生出DML事件时将启用。DML事件即指在表或视图中修改数据的insert、update、delete语句。
        (2)DDL(数据定义语言
Data Definition
Language)触发器:是指当服务器或数据库中生出(DDL事件时将启用。DDL事件即指在表或索引中的create、alter、drop语句也。
        (3)登陆触发器:是指当用户登录SQL
SERVER实例建立会话时接触。

一:触发器的独到之处

 1.触发器是自动的。当对表中的数据做了任何改动将来即刻被激活。

 2.触发器可以经过数据库中的相关表展开层叠修改。

 3.触发器可以强制限制。那个限制比用CHECK约束所定义的更复杂。与CHECK约束不同的是,触发器可以引用其他表中的列。

触发器和存储过程的区别:

1.3.开立触发器

       
其中DML触发器最为常用,遵照DML触发器触发的方法不同又分为以下两种情景:

二:触发器的效益

 触发器的重中之重功用就是其可以落实由主键和外键所不能够担保的复杂参照完整性和数目的一致性,它亦可对数据库中的相关表展开级联修改,提升比CHECK约束更复杂的的数据完整性,并自定义错误音讯。触发器的显要意义重大有以下接个方面:

  1. 强制数据库间的引用完整性
  2. 级联修改数据库中享有有关的表,自动触发其余与之相关的操作
  3. 盯住变化,撤废或回滚违法操作,防止不法修改数据
  4. 再次来到自定义的谬误信息,约束不可能回去信息,而触发器可以
  5. 触发器可以调用更多的储存过程

  触发器与储存过程的界别是运行格局的不等,触发器无法执行EXECUTE语句调用,而是在用户执行Transact-SQL语句时自动触发执行而存储过程需要用户,应用程序或者触发器来体现地调用并推行。

1.3.1.创建DML触发器

     
(1)AFTER触发器:它是在履行INSERT、UPDATE、DELETE语句操作之后执行触发器操作。它至关紧假使用来记录变更后的拍卖或检查,一旦暴发错误,可以用Rollback
Transaction语句来回滚这次扣件,可是不可以对视图定义AFTER触发器。      
(2)INSTEAD
OF触发器:它在推行INSERT、UPDATE、DELETE语句操作在此之前实施触发器本身所定义的操作。而INSTEAD
OF触发器是足以定义在视图上的。

三:触发器的分类

 SqlServer包括二种正常项目标触发器:DML触发器、DDL触发器和登录触发器。

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

 DML触发器是局部附加在特定表或视图上的操作代码,当数据库服务器中发出多少操作语言事件时实施那多少个操作。SqlServer中的DML触发器有两种:

  1. insert触发器:向表中插入数据时被触发;
  2. delete触发器:从表中删除数据时被触发;
  3. update触发器:修改表中多少时被触发。

当遭逢下列意况时,应考虑接纳DML触发器:

  1. 因而数据库中的相关表实现级联更改
  2. 谨防恶意如故失实的insert、update和delete操作,并强制执行check约束定义的限量越来越复杂的其余限制。
  3. 评估数据修改前后表的图景,并按照该距离才去措施。

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

 DDL触发器是当服务器或者数据库中发出多少定义语言(重尽管以create,drop,alter起头的言语)事件时被激活使用,使用DDL触发器可以防范对数据架构举办的一点更改或记录数据中的更改或事件操作。

3.登录触发器

    登录触发器将为响应 LOGIN 事件而振奋存储过程。与 SQL Server 实例建立用户会话时将引发此事件。登录触发器将在报到的身份验证阶段完成之后且用户会话实际建立往日激发。由此,来自触发器内部且平时将抵达用户的持有音信(例如错误消息和来自 PRINT 语句的新闻)会传送到 SQL Server 错误日志。虽然身份验证失败,将不刺激登录触发器。

回到顶部

1.3.1.1.INSERT触发器

示例1:创造一个触发器Automatic_division,当在Student表中插入一条学生音信时,触发器按照入学分数(stu_enter_score)对学生举办机动分班,并在class_student表中插入一条记下。
分班要求:
|Stu_enter_score |Class_id |Class_name|
|——————-|——————|————–|
|stu_enter_score>=700| 01| 创新A班|
|650<=Stu_enter_score<700| 02| 重点B班|
|600<=Stu_enter_score<650| 03| 提高C班|
|550<=Stu_enter_score<600| 04| 普通D班|
|500<=Stu_enter_score<550| 05| 普通E班|
|Stu_enter_score<500| 06| 普通F班|
施行下列语句

CREATE TRIGGER automatic_division
ON student--新建一个检测student表的触发器,命名automatic_division
FOR INSERT--检测到INSERT操作时触发器工作
AS
DECLARE @score INT,@stu_no VARCHAR(8),@class_id CHAR(2)
--声明三个变量
DECLARE stu_cursor CURSOR LOCAL FORWARD_ONLY--声明一个指向inserted表的局部游标stu_cursor
FOR SELECT stu_no,stu_enter_score FROM inserted
OPEN stu_cursor--打开游标
FETCH NEXT FROM stu_cursor INTO @stu_no,@score--将游标指向inserted表的第一个数据并把游标指向的stu_no和stu_enter_score值分别赋值给@stu_no和@score
WHILE @@FETCH_STATUS=0--开始循环
BEGIN
BEGIN--先对@score的数值范围做判断,以确定该学生的班级编号
IF @score>=700
SET @class_id='01'
ELSE IF @score<700 AND @score>=650
SET @class_id='02'
ELSE IF @score<650 AND @score>=600
SET @class_id='03'
ELSE IF @score<600 AND @score>=550
SET @class_id='04'
ELSE IF @score<550 AND @score>=500
SET @class_id='05'
ELSE
SET @class_id='06'
END
--判断结束
INSERT INTO class_student(class_id,stu_no)
VALUES(@class_id,@stu_no)--将数据插入到class_student表中
FETCH NEXT FROM stu_cursor INTO @stu_no,@score--将游标移向inserted表的下一个数据,重复这个循环
END--循环结束
CLOSE stu_cursor--关闭游标
DEALLOCATE stu_cursor--释放游标资源
GO

讲北周码是否正确
student表中插入数据,并查阅class_student表中的数据是否科学

INSERT INTO student(stu_no,stu_name,stu_sex,stu_enter_score)
VALUES('20180001','邹莉莉','女','389'),
('20180002','万兴','男','701'),
('20180003','孙伟','男','652'),
('20180004','温佳静','女','676'),
('20180005','姜立夫','男','542')

Class_student表中的数据如图所示
997755.com澳门葡京 1
游标示例2:对student表中还未分班的学习者开展分班
Student表中的数据如图所示
997755.com澳门葡京 2
其中stu_no20180001~20180005的学童早已在示例1中分班,剩下的学习者全都未分班。
施行下列语句

ALTER TABLE student
ADD stu_division_state bit--为student表新建一列记录是否已分班,true表示已分班
GO
DECLARE stu_class_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT stu_no FROM class_student
--新建游标stu_class_cursor指向class_student表的所有数据
OPEN stu_class_cursor--打开游标
DECLARE @stu_no VARCHAR(8)
FETCH NEXT FROM stu_class_cursor INTO @stu_no
WHILE @@FETCH_STATUS=0
BEGIN
UPDATE student
SET stu_division_state=1
WHERE stu_no=@stu_no
FETCH NEXT FROM stu_class_cursor INTO @stu_no
END
CLOSE stu_class_cursor--关闭游标
DEALLOCATE stu_class_cursor--释放游标资源
---所有学生是否分班已经全部记录在stu_division_state中
GO
DECLARE @stu_no VARCHAR(8),@score INT,@class_id CHAR(2)
DECLARE stu_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT stu_no,stu_enter_score FROM student WHERE stu_division_state IS NULL
--新建student表的游标stu_cursor,指向所有未分班学生
OPEN stu_cursor--打开游标
FETCH NEXT FROM stu_cursor INTO @stu_no,@score
WHILE @@FETCH_STATUS=0--循环开始
BEGIN
BEGIN--先对@score的数值范围做判断,以确定该学生的班级编号
IF @score>=700
SET @class_id='01'
ELSE IF @score<700 AND @score>=650
SET @class_id='02'
ELSE IF @score<650 AND @score>=600
SET @class_id='03'
ELSE IF @score<600 AND @score>=550
SET @class_id='04'
ELSE IF @score<550 AND @score>=500
SET @class_id='05'
ELSE
SET @class_id='06'
END
INSERT INTO class_student(class_id,stu_no)
VALUES(@class_id,@stu_no)--将数据插入到class_student表中
UPDATE student--将student表的stu_division_state改成已分班
SET stu_division_state=1
WHERE stu_no=@stu_no
FETCH NEXT FROM stu_cursor INTO @stu_no,@score--将游标移向inserted表的下一个数据,重复这个循环
END--循环结束
CLOSE stu_cursor
DEALLOCATE stu_cursor
GO

结果如图所示
Student表的数据
997755.com澳门葡京 3
Class_student表的数量
997755.com澳门葡京 4
至此Student表中保有学员都已分班
为了以后方便,可以将游标示例2中的代码稍作修改封装成一个用户自定义存储过程
储存过程示例3
修改后的代码如下

CREATE PROCEDURE student_division
AS
BEGIN
UPDATE student
SET stu_division_state=0--先将student表中所有学生的分班情况都标成未分班

DECLARE stu_class_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT stu_no FROM class_student
--新建游标stu_class_cursor指向class_student表的所有数据
OPEN stu_class_cursor--打开游标
DECLARE @stu_no VARCHAR(8)
FETCH NEXT FROM stu_class_cursor INTO @stu_no
WHILE @@FETCH_STATUS=0
BEGIN
UPDATE student
SET stu_division_state=1
WHERE stu_no=@stu_no--利用游标找出student表中已分班的学生并标记分班状态
FETCH NEXT FROM stu_class_cursor INTO @stu_no
END
CLOSE stu_class_cursor--关闭游标
DEALLOCATE stu_class_cursor--释放游标资源
---所有学生是否分班已经全部记录在stu_division_state中

DECLARE @score INT,@class_id CHAR(2)
DECLARE stu_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT stu_no,stu_enter_score FROM student WHERE stu_division_state=0
--新建student表的游标stu_cursor,指向所有未分班学生
OPEN stu_cursor--打开游标
FETCH NEXT FROM stu_cursor INTO @stu_no,@score
WHILE @@FETCH_STATUS=0--循环开始
BEGIN
BEGIN--先对@score的数值范围做判断,以确定该学生的班级编号
IF @score>=700
SET @class_id='01'
ELSE IF @score<700 AND @score>=650
SET @class_id='02'
ELSE IF @score<650 AND @score>=600
SET @class_id='03'
ELSE IF @score<600 AND @score>=550
SET @class_id='04'
ELSE IF @score<550 AND @score>=500
SET @class_id='05'
ELSE
SET @class_id='06'
END
INSERT INTO class_student(class_id,stu_no)
VALUES(@class_id,@stu_no)--将数据插入到class_student表中
UPDATE student--将student表的stu_division_state改成已分班
SET stu_division_state=1
WHERE stu_no=@stu_no
FETCH NEXT FROM stu_cursor INTO @stu_no,@score--将游标移向inserted表的下一个数据,重复这个循环
END--循环结束
CLOSE stu_cursor
DEALLOCATE stu_cursor
END
GO

注:和游标示例2的代码相相比较,示例3的代码添加了将有着学员分班状态标记为0的过程,去掉了增长stu_division_state列的历程,但对原来已有些学生的分班状态赋值那些手续没有删去,而是举行双重校验。并且删除了两段代码中的GO和第二段用于给学生分班的代码中对@stu_no变量的再一次讲明。

student表插入数据并运行student_division的蕴藏过程

注:对student表插入数据前应先禁用示例1的触发器automatic_division

履行下列语句

ALTER TABLE student DISABLE TRIGGER automatic_division
--禁用automatic_division触发器
INSERT INTO student(stu_no,stu_name,stu_sex,stu_enter_score,stu_division_state)
VALUES('20180006','王洋','男','724',NULL),
('20180007','易阳','男','713',NULL),
('20180008','孙浩','男','584',NULL),
('20180009','张秋燕','女','420','False'),
('20180010','胡燕','女','527','True')

Student表的多少如图所示,红框内就是自我刚好插入还未分班的多寡,其中2018000920180010这多少个学生的分班状态被自己误标成FalseTrue
997755.com澳门葡京 5
履行存储过程

EXEC dbo.student_division

结果如图所示
Student表的多寡(分班状态都为true了)
997755.com澳门葡京 6
Class_student表的数据
997755.com澳门葡京 7

        INSERTED和DELETED

四:触发器的干活原理

触发器触发时:

  1. 系统活动在内存中开创deleted表或inserted表;
  2. 只读,不容许修改,触发器执行到位后,自动删除。

inserted表:

  1. 临时保存了插入或更新后的记录行;
  2. 可以从inserted表中反省插入的多少是否满意工作需求;
  3. 若果不满足,则向用户发送报告错误消息,并回滚插入操作。 

deleted表:

  1. 暂时保存了剔除或更新前的记录行;
  2. 可以从deleted表中反省被删除的数目是否满意工作需要;
  3. 比方不满足,则向用户告知错误音信,并回滚插入操作。

inserted表和deleted表对照: 

修改操作记录 inserted表 deleted表
增加(insert)记录 存放新增的记录 …………
删除(deleted)记录 ………….. 存放被删除的记录
修改(update)记录 存放更新后的记录 存放更新前的记录

 

 

 

997755.com澳门葡京 8

一:触发器的亮点

 1.触发器是全自动的。当对表中的数据做了别样改动之后即刻被激活。

 2.触发器可以经过数据库中的相关表展开层叠修改。

 3.触发器能够强制限制。这么些限制比用CHECK约束所定义的更扑朔迷离。与CHECK约束不同的是,触发器可以引用其他表中的列。

归来顶部

1.3.1.2.DELETE触发器

当针对对象数据库运行DELETE讲话时就会激活DELETE触发器。用户直接运行DELETE言辞和运用DELETE触发器又有所不同,当激活DELETE触发器后,从受触发器影响的表中删除的行会被停放在一个不同平日的临时表——DELETED表中。DELETED表还允许引用由初步化DELETE语句发生的日记数据。
DELETE触发器被激活时,需要考虑以下几点

  • 当某行被添加到DELETED表中时就不存在于数据库表,由此数据库表和DELETED表不容许存在相同行。
  • 系统活动创立DELETED表时,空间从内存中分配。DELETED表被积存在高速缓存中。
  • DELETE操作定义的触发器并不履行TRUNCATE
    TABLE
    话语,原因在于日志不记录TRUNCATE TABLE语句。

示例4:为student表定义一个DELETE触发器,当删除一条学生音讯时,class_student表中该学员的分班音讯也会被删去
实施下边的口舌

CREATE TRIGGER delete_student
ON student
FOR DELETE
AS
DECLARE @stu_no VARCHAR(8)
DECLARE stu_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT stu_no FROM deleted
OPEN stu_cursor
FETCH NEXT FROM stu_cursor INTO @stu_no
WHILE @@FETCH_STATUS=0
BEGIN
DELETE FROM class_student
WHERE stu_no=@stu_no
FETCH NEXT FROM stu_cursor INTO @stu_no
END
CLOSE stu_cursor
DEALLOCATE stu_cursor
GO

测试delete_student触发器的正确
Student表的数目如图所示
997755.com澳门葡京 9
Class_student表的数码如图所示
997755.com澳门葡京 10
执行下列语句

DELETE FROM student
WHERE stu_enter_score<=351
--在student表中删除入学成绩小于分的学生

student表来看,只有入学编号为2018001120180012的学生战表被删除。该操作激活了delete_student触发器
Class_student表的数目如图所示
997755.com澳门葡京 11
入学编号为2018001120180012的学生分班信息已经从class_student表中活动删除。

        在SQL SERVER
2008中,DML触发器的落实利用多少个逻辑表DELETED和INSERTED。这六个表是确立在数据库服务器的内存中,大家唯有只读的权限。DELETED和INSERED表的社团和触发器所在的数据表的布局是均等的。当触发器执行到位后,它们也就会被自动删除:INSERED表用于存放你在操件insert、update、delete语句后,更新的记录。比如您插入一条数据,那么就会把这条记下插入到INSERTED表:DELETED表用于存放你在操作 
insert、update、delete语句前,你创设触发器表中数据库。比如你本来的表中有三条数据,那么他也有三条数据。也就是说,我们可以运用这六个临时的驻留内存的表,测试某些数据修改的效率及安装触发器操作的口径。

五:成立触发器

 创设触发器的语法: 

CREATE TRIGGER trigger_name
 ON table_name
 [WITH ENCRYPTION]
  FOR | AFTER | INSTEAD OF [DELETE, INSERT, UPDATE]
 AS 
  T-SQL语句
GO
--with encryption 表示加密触发器定义的sql文本
--delete,insert,update指定触发器的类型

 准备测试数据:

--创建学生表
create table student(
    stu_id int identity(1,1) primary key,
    stu_name varchar(10),
    stu_gender char(2),
    stu_age int
)

1.创建insert触发器

--创建insert触发器
create trigger trig_insert
on student
after insert
as
begin
    if object_id(N'student_sum',N'U') is null--判断student_sum表是否存在
        create table student_sum(stuCount int default(0));--创建存储学生人数的student_sum表
    declare @stuNumber int;
    select @stuNumber = count(*)from student;
    if not exists (select * from student_sum)--判断表中是否有记录
        insert into student_sum values(0);
    update student_sum set stuCount =@stuNumber; --把更新后总的学生数插入到student_sum表中
end

--测试触发器trig_insert-->功能是向student插入数据的同时级联插入到student_sum表中,更新stuCount
--因为是后触发器,所以先插入数据后,才触发触发器trig_insert;
insert into student(stu_name,stu_gender,stu_age)values('吕布','男',30);
select stuCount 学生总人数 from student_sum;    
insert into student(stu_name,stu_gender,stu_age)values('貂蝉','女',30);            
select stuCount 学生总人数 from student_sum;
insert into student(stu_name,stu_gender,stu_age)values('曹阿瞒','男',40);                
select stuCount 学生总人数 from student_sum;

推行下面的说话后,结果如下图所示:

997755.com澳门葡京 12

 既然定义了学员总数表student_sum表是向student表中插入数据后才总计学生总数的,所以学生总数表应该禁止用户向其中插入数据

--创建insert_forbidden,禁止用户向student_sum表中插入数据
create trigger insert_forbidden
on student_sum
after insert
as
begin
    RAISERROR('禁止直接向该表中插入记录,操作被禁止',1,1)--raiserror 是用于抛出一个错误
rollback transaction
end 

--触发触发器insert_forbidden
insert student_sum (stuCount) values(5);

结果如下:

997755.com澳门葡京 13

 2.创建delete触发器

  用户执行delete操作,就会激活delete触发器,从而控制用户可以从数据库中删去数据记录,触发delete触发器后,用户删除的记录会被添加到deleted表中,原来表的应和记录被剔除,所以在deleted表中查阅删除的记录。

--创建delete触发器
create trigger trig_delete
on student 
after delete
as
begin
    select stu_id as 已删除的学生编号,stu_name stu_gender,stu_age
    from deleted
end;

--执行一一条delete语句触发trig_delete触发器
delete from student where stu_id=1;

结果如下:

997755.com澳门葡京 14

 3.创建UPDATE触发器

  update触发器是当用户在指定表上举行update语句时被调用被调用,这系列型的触发器用来约束用户对数码的修改。update触发器可以实施二种操作:更新前的笔录存储在deleted表中,更新后的记录存储在inserted表中。

--创建update触发器
create trigger trig_update
on student
after update
as
begin
    declare @stuCount int;
    select @stuCount=count(*) from student;
    update student_sum set stuCount =@stuCount;
    select stu_id as 更新前学生编号,stu_name as 更新前学生姓名 from deleted
    select stu_id as 更新后学生编号,stu_name as 更新后学生姓名 from inserted
end

--创建完成,执行一条update语句触发trig_update触发器
update student set stu_name='张飞' where stu_id=2;

997755.com澳门葡京 15

 4.开立替代触发器

  与眼前介绍的二种after触发器不同,SqlServer服务器在执行after触发器的sql代码后,先创造临时的inserted表和deleted表,然后实施代码中对数据库操作,最终才激活触发器中的代码。而对于代表(instead
of**
)触发器,SqlServer服务器在执行触发instead
of
触发器的代码时,先成立
暂时的inserted表和deleted表,然后直接触发instead
of触发器,而拒绝执行用户输入的DML操作语句。**

--创建instead of 触发器 
create trigger trig_insteadOf
on student 
instead of insert
as 
begin
    declare @stuAge int;
    select @stuAge=(select stu_age from inserted)
if(@stuAge >120)
    select '插入年龄错误' as '失败原因'
end

创立完成,执行一条insert语句触发触发器trig_insteadOf

997755.com澳门葡京 16

5.嵌套触发器介绍

 假诺一个触发器在履行操作时调用了另外一个触发器,而以此触发器又跟着调用了下一个触发器,那么就形成了嵌套触发器。嵌套触发器在设置时就被启用,可是可以运用系统存储过程sp_configure禁用和重复启用嵌套触发器。

 

  嵌套触发器不必然要形成一个环,它可以 T1->T2->T3…这样直白触发下去,最多允许嵌套 32 层。假使嵌套的次数超越限制,那么该触发器将被截至,并回滚整个事情,使用嵌套触发器需要注意以下几点:

  • 默认情形下,嵌套触发器配置选项是开启的。
  • 在同一个触发器事务中,一个嵌套触发器无法被触发一回。
  • 由于触发器是一个事务,假诺在一雨后春笋嵌套触发器的随机层次中发出错误,则整个事物都将吊销,而且装有数据回滚。

嵌套是用来保障总体数据库的完整性的重大效率,但偶尔可能需要禁用嵌套,如果禁用了嵌套,那么修改一个触发器的贯彻不会再接触该表上的其他触发器。在下述情况下,需要禁用嵌套触发器:

  • 嵌套触发要求复杂而有理论的计划性,级联修改或者会修改用户不想涉及的数量。
  • 在一多样嵌套触发器中的任意点的时光修改操作都会触发一些触发器,固然这时数据库提供很强的保障功效,但倘诺以一定的一一更新表,就会发出问题。

接纳下列语句禁用嵌套和再一次启用嵌套:

--禁用嵌套
exce sp_configure 'nested triggers',0;
--启用嵌套
exce sp_configure 'nested triggers',1;

6.递归触发器

  触发器的递归是指一个触发器从其里面再四次激活该触发器,例如update操作激活的触发器内部还有一条数据表的换代语句,那么这个改进语句就有可能激活那个触发器本身,当然,这种递归的触发器内部还会有咬定语句,只有早晚情状下才会执行这个T_SQL语句,否则就变成无线调用的死循环了。

SqlServer中的递归触发器包括二种:直接递归和直接递归。

  • 向来递归:触发器被触发后并履行一个操作,而该操作又利用一个触发器再一次被触发。
  • 间接递归:触发器被触发并推行一个操作,而该操作又使另一个表中的某个触发器被触发,第二个触发器使原始表得到更新,从而再一次接触第一个触发器。

默认处境下,递归触发器选项是剥夺的。递归触发器最五只好递归16层,若是递归中的第16个触发器激活了第17个触发器,则结果与发布的rollback命令一样,所有数据都将回滚。 

咱俩举例表达如下,假设有表1、表2名称分别为 T1、T2,在 T1、T2 上各自有触发器 G1、G2。

  • 直接递归:对 T1 操作从而触发 G1,G1 对 T2 操作从而触发 G2,G2 对 T1 操作从而再度触发 G1…
  • 一直递归:对 T1 操作从而触发 G1,G1 对 T1 操作从而再一次触发 G1… 

设置直接递归:

默认情况下是禁止直接递归的,要安装为允许有二种模式:

  • T-SQL:exec sp_dboption ‘dbName’, ‘recursive triggers’, true;
  • EM:数据库上点右键->属性->选项。 

二:触发器的功用

 触发器的严重性成效就是其可以落实由主键和外键所不可能担保的纷繁参照完整性和数据的一致性,它亦可对数据库中的相关表展开级联修改,提升比CHECK约束更复杂的的数据完整性,并自定义错误信息。触发器的显要职能重要有以下接个方面:

  1. 强制数据库间的引用完整性
  2. 级联修改数据库中保有有关的表,自动触发另外与之相关的操作
  3. 盯住变化,取消或回滚违法操作,制止不法修改数据
  4. 回到自定义的错误音信,约束不可能重回音信,而触发器可以
  5. 触发器可以调用更多的囤积过程

回去顶部

1.3.1.3.UPDATE触发器

当针对对象数据库运行UPDATE言辞时就会激活UPDATE触发器。对UPDATE触发器来说,临时表INSERTEDDELETED如故有效。UPDATE触发器被激活时,原始行被移入DELETED表中,更新行被移入到INSERTED表中。触发器检查DELETED表和INSERTED表以及被更新的表,来确定是否更新了多行和怎么样实施触发器动作。
Student表的多少如图所示
997755.com澳门葡京 17
Class_student表的多寡如图所示
997755.com澳门葡京 18
示例5:当student表中的stu_no字段更新时,同步改进class_student表中的stu_no字段
进行下列语句新建触发器update_stu_no_single

CREATE TRIGGER update_stu_no_single
ON student
FOR UPDATE
AS
IF UPDATE(stu_no)
BEGIN
UPDATE class_student
SET stu_no=(SELECT stu_no FROM inserted)
WHERE stu_no=(SELECT stu_no FROM deleted)
END
GO

验证update_stu_no_single触发器是否正确,在Student表中执行下列语句,将student表中stu_no为“20180101”的学员的stu_no改成00000000

UPDATE student
SET stu_no='00000000'
WHERE stu_no='20180101'

实践成功后,update_stu_no_single触发器被激活,class_student表的数目如图所示
997755.com澳门葡京 19

注:update_stu_no_single触发器只可以对单行记录的UPDATE操作起效,尽管批量UPDATE
stu_no
,执行语句时会提示子查询再次来到的值持续1个。下边的示例6将提供批量UPDATE
stu_no
的触发器

示例6:实现当student表的stu_no字段批量更新时,class_student表的stu_no也一路批量翻新
首先将student表和class_student表的多少修改成原本的指南,并且删除update_stu_no_single触发器
Student表的数据如图所示
997755.com澳门葡京 20
Class_student表的数量如图所示
997755.com澳门葡京 21
推行下列语句新建触发器update_stu_no_batch

CREATE TRIGGER update_stu_no_batch
ON student
FOR UPDATE
AS
DECLARE @stu_no_insert VARCHAR(8),@stu_no_delete VARCHAR(8)
DECLARE stu_cursor_insert CURSOR LOCAL FORWARD_ONLY
FOR SELECT stu_no FROM inserted
OPEN stu_cursor_insert
DECLARE stu_cursor_delete CURSOR LOCAL FORWARD_ONLY
FOR SELECT stu_no FROM deleted
OPEN stu_cursor_delete
FETCH NEXT FROM stu_cursor_insert INTO @stu_no_insert
FETCH NEXT FROM stu_cursor_delete INTO @stu_no_delete
WHILE @@FETCH_STATUS=0
BEGIN
UPDATE class_student
SET stu_no=@stu_no_insert
WHERE stu_no=@stu_no_delete
FETCH NEXT FROM stu_cursor_insert INTO @stu_no_insert
FETCH NEXT FROM stu_cursor_delete INTO @stu_no_delete
END
CLOSE stu_cursor_insert
CLOSE stu_cursor_delete
DEALLOCATE stu_cursor_insert
DEALLOCATE stu_cursor_delete
GO

验证update_stu_no_batch触发器的准确性,对student表执行下列语句,实现批量修改操作

UPDATE student
SET stu_no='00000000'
WHERE stu_no LIKE '201801%'
GO

Student表的数据如图所示
997755.com澳门葡京 22
Class_student表的数量如图所示
997755.com澳门葡京 23
我们再来验证update_stu_no_batch触发器对革新单行stu_no数量是否管用。将student表class_student表的数据改回原来的规范,然后实施下列语句

UPDATE student
SET stu_no='00000000'
WHERE stu_no='20180101'

Class_student表的数目如图所示
997755.com澳门葡京 24

注:在将表数据改成原本的指南时,直接在编排前200行中操作仍旧用T-SQL言辞操作,对student表数据操作,不成事的话要考虑受键和约束的熏陶,对class_student表数据操作,不成功的话要考虑受触发器影响。

        触发器的利弊:

六:管理触发器 

1.查看触发器

(1).查看数据库中装有的触发器

--查看数据库中所有的触发器
use 数据库名
go
select * from sysobjects where xtype='TR'

sysobjects 保存着数据库的靶子,其中 xtype 为 TR 的笔录即为触发器对象。在 name 一列,我们可以观看触发器名称。

(2).sp_helptext 查看触发器内容

use 数据库名
go
exec sp_helptext '触发器名称'

 将会以表的样式呈现触发器内容。 

 除了触发器外,sp_helptext 还足以突显 规则、默认值、未加密的贮存过程、用户定义函数、视图的文件。

(3).sp_helptrigger 用于查看触发器的习性

  sp_helptrigger 有五个参数:第一个参数为表名;第二个为触发器类型,为 char(6) 类型,能够是 INSERT、UPDATE、DELETE,倘使简单则体现指定表中所有类型触发器的特性。

use 数据库名
go
exec sp_helptrigger tableName

2.禁用启用触发器

  禁用:alter table 表名 disable trigger 触发器名称
  启用:alter table 表名 enable trigger 触发器名称

  倘使有两个触发器,则相继触发器名称之间用英文逗号隔开。

  倘若把“触发器名称”换成“ALL”,则意味着禁用或启用该表的整个触发器。

3修改触发器

--修改触发器语法
ALTER TRIGGER  trigger_name 
     ON  table_name 
     [ WITH ENCRYPTION ] 
     FOR {[DELETE][,][INSERT][,][UPDATE]}
     AS
       sql_statement;

4.删减触发器

 --语法格式:
      DROP  TRIGGER   { trigger } [ ,...n ]
参数:
 trigger: 要删除的触发器名称
 n:表示可以删除多个触发器的占位符       

三:触发器的归类

 SqlServer包括二种健康项目标触发器:DML触发器、DDL触发器和登录触发器。

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

 DML触发器是有的外加在特定表或视图上的操作代码,当数据库服务器中发出多少操作语言事件时举行这多少个操作。SqlServer中的DML触发器有三种:

  1. insert触发器:向表中插入数据时被触发;
  2. delete触发器:从表中删除数据时被触发;
  3. update触发器:修改表中数据时被触发。

当遭遇下列状况时,应考虑使用DML触发器:

  1. 经过数据库中的相关表实现级联更改
  2. 制止恶意仍然不当的insert、update和delete操作,并强制执行check约束定义的界定越来越复杂的别样限制。
  3. 评估数据修改前后表的状态,并依据该出入才去措施。

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

 DDL触发器是当服务器或者数据库中暴发多少定义语言(重假若以create,drop,alter最先的口舌)事件时被激活使用,使用DDL触发器能够预防对数码架构举行的某些更改或记录数据中的更改或事件操作。

3.登录触发器

    登录触发器将为响应 LOGIN 事件而振奋存储过程。与 SQL Server 实例建立用户会话时将抓住此事件。登录触发器将在报到的身份验证阶段完成未来且用户会话实际建立从前激发。由此,来自触发器内部且一般将到达用户的享有音讯(例如错误音讯和来自 PRINT 语句的信息)会传递到 SQL Server 错误日志。如若身份验证失利,将不刺激登录触发器。

再次回到顶部

1.3.1.4.INSTEAD OF触发器

INSTEAD
OF
触发器可以指定执行触发器,而不是实践触发SQL讲话,从而屏蔽原来的SQL言语,而转用执行触发器内部的话语。每个表或者视图只好有1个INSTEAD
OF
触发器。INSTEAD
OF
触发器的特征是,可以使作为触发条件的SQL语句不举行。
Membership表的数额如图所示
997755.com澳门葡京 25
Call_slip表的多少如图所示
997755.com澳门葡京 26
示例7:对LibraryManagement数据库里的membership表写一个防删除触发器,尚有借书未还的读者无法被去除
履行下列语句创造member_delete_single触发器

CREATE TRIGGER member_delete_single
ON membership
INSTEAD OF DELETE
AS
BEGIN
IF NOT EXISTS(SELECT * FROM call_slip WHERE member_id=(SELECT member_id FROM deleted) AND borrow_state='未归还')
DELETE FROM membership WHERE member_id=(SELECT member_id FROM deleted)
ELSE
BEGIN
SELECT '该用户尚有图书未还,无法删除'
SELECT * FROM call_slip WHERE member_id=(SELECT member_id FROM deleted) AND borrow_state='未归还'
END
END
GO

表明触发器的不易,执行下列语句

DELETE FROM membership
WHERE member_id='20060128'

结果如图所示
997755.com澳门葡京 27
该触发器只针对DELETE一条数据有效
示例8:对LibraryManagement数据库里的membership表写一个防批量删除触发器,尚有借书未还的读者不能被剔除
Membership表的数据如图所示
997755.com澳门葡京 28
Call_slip表的数量如图所示
997755.com澳门葡京 29
履行下列语句新建触发器(将示例7中的member_delete_single触发器先删除)

CREATE TRIGGER member_delete_batch
ON membership
INSTEAD OF DELETE
AS
BEGIN
DECLARE member_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT member_id FROM deleted
OPEN member_cursor
DECLARE @member_id VARCHAR(8)
FETCH NEXT FROM member_cursor INTO @member_id
WHILE @@FETCH_STATUS=0
BEGIN
BEGIN
IF NOT EXISTS(SELECT* FROM call_slip WHERE member_id=@member_id AND borrow_state='未归还')
DELETE FROM membership WHERE member_id=@member_id
ELSE
PRINT '用户'+@member_id+'无法删除'
END
FETCH NEXT FROM member_cursor INTO @member_id
END
CLOSE member_cursor
DEALLOCATE member_cursor
END
GO

结果如图所示
997755.com澳门葡京 30
Membership表的多寡如图所示
997755.com澳门葡京 31
示例9:对LibraryManagement数据库里的call_slip表写一个防超借触发器,一个读者的未还图书最六只可以有5本,超出不可以再借(这里依旧针对批量处理数量创建触发器)
Call_slip表的数据如图所示
997755.com澳门葡京 32
推行下列语句创制provent_overborrowing_batch触发器

CREATE TRIGGER provent_overborrowing_batch
ON call_slip
INSTEAD OF INSERT
AS
BEGIN
DECLARE @member_id VARCHAR(8)
DECLARE borrow_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT DISTINCT member_id FROM inserted
OPEN borrow_cursor
FETCH NEXT FROM borrow_cursor INTO @member_id
WHILE @@FETCH_STATUS=0
BEGIN
BEGIN
IF (SELECT COUNT(*) FROM call_slip WHERE member_id=@member_id AND borrow_state='未归还')<5
INSERT INTO call_slip SELECT * FROM inserted WHERE member_id=@member_id
ELSE
PRINT '用户'+@member_id+'已借阅且未还的图书超过5本,无法再借'
END
FETCH NEXT FROM borrow_cursor INTO @member_id
END
END
GO

履行下列语句测试provent_overborrowing_batch触发器的不易,其中member_id为“20060128”的用户借书未还超过5本,应该是力不从心再借的。

--测试数据
INSERT INTO call_slip(book_id,member_id,loan_period,borrow_state)
VALUES('20130002','20060128','30','未归还'),
('20130001','20060128','20','未归还'),
('20130003','20060128','30','未归还'),
('20130004','20062919','30','未归还'),
('20130005','20150821','45','未归还')

结果如图所示
997755.com澳门葡京 33
Call_slip表的数额如图所示,红框里是新插入的多少
997755.com澳门葡京 34

     
  触发器可透过数据库中的相关表实现级联更改,可以强制比用CHECK约束定义的约束越来越复杂的约束。与
CHECK
约束不同,触发器可以引用此外表中的列,例如触发器能够利用另一个表中的
SELECT
相比插入或更新的数目,以及履行其余操作。触发器也得以遵照数据修改前后的表状态,再行采纳对策。一个表中的多个同类触发器(INSERT、UPDATE
或 DELETE)允许采用五个例外的心计以响应同一个改动语句。

四:触发器的干活规律

触发器触发时:

  1. 系统自动在内存中开创deleted表或inserted表;
  2. 只读,不容许修改,触发器执行到位后,自动删除。

inserted表:

  1. 暂时保存了插入或更新后的记录行;
  2. 可以从inserted表中反省插入的数据是否满意工作要求;
  3. 一旦不满足,则向用户发送报告错误音讯,并回滚插入操作。 

deleted表:

  1. 临时保存了去除或更新前的记录行;
  2. 可以从deleted表中反省被剔除的多少是否满意工作需求;
  3. 假定不满意,则向用户告知错误音讯,并回滚插入操作。

inserted表和deleted表对照: 

修改操作记录 inserted表 deleted表
增加(insert)记录 存放新增的记录 …………
删除(deleted)记录 ………….. 存放被删除的记录
修改(update)记录 存放更新后的记录 存放更新前的记录

 

 

 

997755.com澳门葡京 35

回去顶部

1.3.2.创建DDL触发器

DDL触发器只为了响应CREATEDROPALTER事件而激活,它的效能域是所有数据库或者服务器,而不是功效域某张表或准备。它可以使得控制哪位用户可以修改数据库结构以及怎样修改。
示例10:创制一个DDL触发器,控制上班时间(8:00-18:00)不能对LibraryManagement数据库表和试图结构举行新建,修改和删除操作。
实施下列语句创建触发器deny_DDL_table

CREATE TRIGGER deny_DDL_table
ON DATABASE
WITH ENCRYPTION
FOR CREATE_TABLE,DROP_TABLE,ALTER_TABLE
AS
DECLARE @eventdata XML
SET @eventdata=EVENTDATA()
IF(DATEPART(HOUR,GETDATE()) BETWEEN 8 AND 17)
BEGIN
SELECT '触发器deny_DDL_table已禁止工作时间8:00-18:00对LibraryManagement数据库的CREATE,ALTER,DROP操作'
SELECT @eventdata.value('(/EVENT_INSTANCE/EventType)[1]','nvarchar(max)') AS EventType,--事件类型
@eventdata.value('(/EVENT_INSTANCE/PostTime)[1]','nvarchar(max)') AS PostTime,--时间触发的时间
@eventdata.value('(/EVENT_INSTANCE/DatabaseName)[1]','nvarchar(max)') AS DatabaseName,--数据库名字
@eventdata.value('(/EVENT_INSTANCE/ObjectName)[1]','nvarchar(max)') AS ObjectName,--操作的对象名称
@eventdata.value('(/EVENT_INSTANCE/ObjectType)[1]','nvarchar(max)') AS ObjectType,--操作的对象类型
@eventdata.value('(/EVENT_INSTANCE/TSQLCommand/CommandText)[1]','nvarchar(max)') AS CommandText--操作命令文本
ROLLBACK---对操作进行回滚,也可以不回滚
END
GO

举行以下代码以测试DDL触发器deny_DDL_table的不利

USE LibraryManagement
CREATE TABLE test(
t_id VARCHAR(2),
t_name VARCHAR(20)
)

结果如图所示
997755.com澳门葡京 36
997755.com澳门葡京 37

注:EVENTDATA()可在触发器内部使用,再次来到有关数据库和服务器事件的新闻,以XML格式重临。只有一向在DDL或登录触发器内部引用EVENTDATA时,EVENTDATA才会回来数据。如果EVENTDATA由另外例程调用(固然这多少个例程由DDL或登录触发器举行调用),将回来
NULL

       
与此同时,即便触发器功用强大,轻松可靠地贯彻无数错综复杂的效果,为什么又要慎用?过多触发器会促成数据库及应用程序的掩护困难,同时对触发器过分的依靠,势必影响数据库的结构,同时扩大了保安的错综复杂程序。

五:创建触发器

 创制触发器的语法: 

997755.com澳门葡京 38😉

CREATE TRIGGER trigger_name
 ON table_name
 [WITH ENCRYPTION]
  FOR | AFTER | INSTEAD OF [DELETE, INSERT, UPDATE]
 AS 
  T-SQL语句
GO
--with encryption 表示加密触发器定义的sql文本
--delete,insert,update指定触发器的类型

997755.com澳门葡京 39😉

 准备测试数据:

997755.com澳门葡京 40😉

--创建学生表
create table student(
    stu_id int identity(1,1) primary key,
    stu_name varchar(10),
    stu_gender char(2),
    stu_age int
)

997755.com澳门葡京 41😉

1.创建insert触发器

997755.com澳门葡京 42😉

--创建insert触发器
create trigger trig_insert
on student
after insert
as
begin
    if object_id(N'student_sum',N'U') is null--判断student_sum表是否存在
        create table student_sum(stuCount int default(0));--创建存储学生人数的student_sum表
    declare @stuNumber int;
    select @stuNumber = count(*)from student;
    if not exists (select * from student_sum)--判断表中是否有记录
        insert into student_sum values(0);
    update student_sum set stuCount =@stuNumber; --把更新后总的学生数插入到student_sum表中
end

997755.com澳门葡京 43😉

997755.com澳门葡京 44😉

--测试触发器trig_insert-->功能是向student插入数据的同时级联插入到student_sum表中,更新stuCount
--因为是后触发器,所以先插入数据后,才触发触发器trig_insert;
insert into student(stu_name,stu_gender,stu_age)values('吕布','男',30);
select stuCount 学生总人数 from student_sum;    
insert into student(stu_name,stu_gender,stu_age)values('貂蝉','女',30);            
select stuCount 学生总人数 from student_sum;
insert into student(stu_name,stu_gender,stu_age)values('曹阿瞒','男',40);                
select stuCount 学生总人数 from student_sum;

997755.com澳门葡京 45😉

实践上边的口舌后,结果如下图所示:

997755.com澳门葡京 46

 既然定义了学员总数表student_sum表是向student表中插入数据后才总括学生总数的,所以学生总数表应该禁止用户向里面插入数据

997755.com澳门葡京 47😉

--创建insert_forbidden,禁止用户向student_sum表中插入数据
create trigger insert_forbidden
on student_sum
after insert
as
begin
    RAISERROR('禁止直接向该表中插入记录,操作被禁止',1,1)--raiserror 是用于抛出一个错误
rollback transaction
end 

997755.com澳门葡京 48😉

--触发触发器insert_forbidden
insert student_sum (stuCount) values(5);

结果如下:

997755.com澳门葡京 49

 2.创建delete触发器

  用户执行delete操作,就会激活delete触发器,从而控制用户可以从数据库中删除数据记录,触发delete触发器后,用户删除的记录会被添加到deleted表中,原来表的附和记录被剔除,所以在deleted表中查阅删除的记录。

997755.com澳门葡京 50😉

--创建delete触发器
create trigger trig_delete
on student 
after delete
as
begin
    select stu_id as 已删除的学生编号,stu_name stu_gender,stu_age
    from deleted
end;

997755.com澳门葡京 51😉

--执行一一条delete语句触发trig_delete触发器
delete from student where stu_id=1;

结果如下:

997755.com澳门葡京 52

 3.创建UPDATE触发器

  update触发器是当用户在指定表上举办update语句时被调用被调用,这序列型的触发器用来约束用户对数码的修改。update触发器可以实施二种操作:更新前的笔录存储在deleted表中,更新后的记录存储在inserted表中。

997755.com澳门葡京 53😉

--创建update触发器
create trigger trig_update
on student
after update
as
begin
    declare @stuCount int;
    select @stuCount=count(*) from student;
    update student_sum set stuCount =@stuCount;
    select stu_id as 更新前学生编号,stu_name as 更新前学生姓名 from deleted
    select stu_id as 更新后学生编号,stu_name as 更新后学生姓名 from inserted
end

997755.com澳门葡京 54😉

--创建完成,执行一条update语句触发trig_update触发器
update student set stu_name='张飞' where stu_id=2;

997755.com澳门葡京 55

 4.开立替代触发器

  与前面介绍的二种after触发器不同,SqlServer服务器在实施after触发器的sql代码后,先成立临时的inserted表和deleted表,然后实施代码中对数据库操作,最后才激活触发器中的代码。而对此代表(instead
of**
)触发器,SqlServer服务器在执行触发instead
of
触发器的代码时,先创立
临时的inserted表和deleted表,然后径直触发instead
of触发器,而拒绝执行用户输入的DML操作语句。**

997755.com澳门葡京 56😉

--创建instead of 触发器 
create trigger trig_insteadOf
on student 
instead of insert
as 
begin
    declare @stuAge int;
    select @stuAge=(select stu_age from inserted)
if(@stuAge >120)
    select '插入年龄错误' as '失败原因'
end

997755.com澳门葡京 57😉

始建完成,执行一条insert语句触发触发器trig_insteadOf

997755.com澳门葡京 58

5.嵌套触发器介绍

 尽管一个触发器在履行操作时调用了另外一个触发器,而以此触发器又随即调用了下一个触发器,那么就形成了嵌套触发器。嵌套触发器在设置时就被启用,可是可以动用系统存储过程sp_configure禁用和再一次启用嵌套触发器。

997755.com澳门葡京, 

  嵌套触发器不自然要形成一个环,它可以 T1->T2->T3…这样直接触发下去,最多允许嵌套 32 层。假设嵌套的次数超越限制,那么该触发器将被终止,并回滚整个工作,使用嵌套触发器需要小心以下几点:

  • 默认情状下,嵌套触发器配置选项是敞开的。
  • 在同一个触发器事务中,一个嵌套触发器不可以被触发五遍。
  • 是因为触发器是一个事务,假若在一密密麻麻嵌套触发器的随意层次中发生错误,则整个事物都将注销,而且拥有数据回滚。

嵌套是用来维系整个数据库的完整性的严重性职能,但有时候可能需要禁用嵌套,假若禁用了嵌套,那么修改一个触发器的兑现不会再触及该表上的其余触发器。在下述意况下,需要禁用嵌套触发器:

  • 嵌套触发要求复杂而有理论的规划,级联修改或者会修改用户不想涉及的数额。
  • 在一多样嵌套触发器中的任意点的时辰修改操作都会接触一些触发器,尽管这时数据库提供很强的掩护效率,但假诺以特定的顺序更新表,就会生出问题。

行使下列语句禁用嵌套和重复启用嵌套:

--禁用嵌套
exce sp_configure 'nested triggers',0;
--启用嵌套
exce sp_configure 'nested triggers',1;

6.递归触发器

  触发器的递归是指一个触发器从其内部再五遍激活该触发器,例如update操作激活的触发器内部还有一条数据表的翻新语句,那么那些改进语句就有可能激活这么些触发器本身,当然,这种递归的触发器内部还会有咬定语句,只有自然意况下才会履行那多少个T_SQL语句,否则就成为无线调用的死循环了。

SqlServer中的递归触发器包括二种:直接递归和直接递归。

  • 一向递归:触发器被触发后并履行一个操作,而该操作又利用一个触发器再一次被触发。
  • 直接递归:触发器被触发并推行一个操作,而该操作又使另一个表中的某个触发器被触发,第二个触发器使原始表拿到更新,从而再一次接触第一个触发器。

默认意况下,递归触发器选项是剥夺的。递归触发器最两只好递归16层,假使递归中的第16个触发器激活了第17个触发器,则结果与发布的rollback命令一样,所有数据都将回滚。 

大家举例表达如下,假若有表1、表2名号分别为 T1、T2,在 T1、T2 上独家有触发器 G1、G2。

  • 直接递归:对 T1 操作从而触发 G1,G1 对 T2 操作从而触发 G2,G2 对 T1 操作从而再度触发 G1…
  • 直接递归:对 T1 操作从而触发 G1,G1 对 T1 操作从而再次触发 G1… 

设置直接递归:

默认情形下是明令禁止直接递归的,要设置为允许有三种方法:

  • T-SQL:exec sp_dboption ‘dbName’, ‘recursive triggers’, true;
  • EM:数据库上点右键->属性->选项。 

回去顶部

1.3.3.嵌套触发器

语法

六:管理触发器 

1.查看触发器

(1).查看数据库中具备的触发器

--查看数据库中所有的触发器
use 数据库名
go
select * from sysobjects where xtype='TR'

sysobjects 保存着数据库的目的,其中 xtype 为 TR 的笔录即为触发器对象。在 name 一列,大家可以看到触发器名称。

(2).sp_helptext 查看触发器内容

use 数据库名
go
exec sp_helptext '触发器名称'

 将会以表的体裁显示触发器内容。 

 除了触发器外,sp_helptext 还足以体现 规则、默认值、未加密的仓储过程、用户定义函数、视图的文书。

(3).sp_helptrigger 用于查看触发器的属性

  sp_helptrigger 有三个参数:第一个参数为表名;第二个为触发器类型,为 char(6) 类型,可以是 INSERT、UPDATE、DELETE,假若简单则显得指定表中所有品种触发器的性能。

use 数据库名
go
exec sp_helptrigger tableName

2.禁用启用触发器

  禁用:alter table 表名 disable trigger 触发器名称
  启用:alter table 表名 enable trigger 触发器名称

  倘使有两个触发器,则相继触发器名称之间用英文逗号隔开。

  假使把“触发器名称”换成“ALL”,则意味着禁用或启用该表的全体触发器。

3修改触发器

997755.com澳门葡京 59😉

--修改触发器语法
ALTER TRIGGER  trigger_name 
     ON  table_name 
     [ WITH ENCRYPTION ] 
     FOR {[DELETE][,][INSERT][,][UPDATE]}
     AS
       sql_statement;

997755.com澳门葡京 60😉

4.删减触发器

 --语法格式:
      DROP  TRIGGER   { trigger } [ ,...n ]
参数:
 trigger: 要删除的触发器名称
 n:表示可以删除多个触发器的占位符       

原文转自:

1.3.3.1.嵌套触发器

只要一个触发器在举办操作时引发了另一个触发器,而以此触发器又掀起了下一个触发器,那么这么些触发器就是嵌套触发器。嵌套触发器在安装时就被启用,不过足以使用sp_configure积存过程禁用和重复启用嵌套。
DML触发器和DDL触发器最多可以嵌套32层,可以经过nested
triggers
来配置是否可以嵌套AFTER触发器,可是无论是此设置哪些都可以嵌套INSTEAD
OF
触发器。如若嵌套触发器进入了然则循环,该触发器将被截至,并且回滚整个业务。嵌套触发器具有多种用场,比如保留前一个触发器所影响的行的副本。
使用嵌套触发器时应有专注以下几点:

  • 默认境况下,嵌套触发器配置选项开启。
  • 在同一个触发器事务中,一个触发器不会被触发一遍,触发器不会调用他自己来响应触发器中对同一个表的第二次革新
  • 出于触发器是一个工作,一旦嵌套中此外一层的触发器出现谬误,将回滚整个事情。

示例11:有teacher_course表(助教所教学程表),course表(课程表)和course_selection表(学生选课表),写一个嵌套触发器,实现课程撤消后,删除助教所教学程表中有关该学科的记录,而教授所讲师程表中该科目标笔录被收回,导致该课程的学童选课记录也做相应撤销。
实践下列语句

--创建course表上的触发器,删除course表中的课程,teacher_course表中的记录做对应删除
CREATE TRIGGER course_delete_batch
ON course
FOR DELETE
AS
DECLARE @course_id CHAR(4)
DECLARE course_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT course_id FROM deleted
OPEN course_cursor
FETCH NEXT FROM course_cursor INTO @course_id
WHILE @@FETCH_STATUS=0
BEGIN
DELETE FROM teacher_course WHERE course_id=@course_id
FETCH NEXT FROM course_cursor INTO @course_id
END
GO
--创建teacher_course表上的触发器,删除教师课程表的记录,学生选课表的记录也做对应删除
CREATE TRIGGER teacher_course_delete_batch
ON teacher_course
FOR DELETE
AS
DECLARE @course_id CHAR(4)
DECLARE teacher_course_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT DISTINCT course_id FROM deleted
OPEN teacher_course_cursor
FETCH NEXT FROM teacher_course_cursor INTO @course_id
WHILE @@FETCH_STATUS=0
BEGIN
IF (SELECT COUNT(*) FROM teacher_course WHERE course_id=@course_id)=0
DELETE FROM course_selection WHERE course_id=@course_id
ELSE
PRINT 'course_id为'+@course_id+'的课程依然正常开课,该课程的学生选课情况不予删除'
FETCH NEXT FROM teacher_course_cursor INTO @course_id
END
GO

course_delete_batch和**
teacher_course_delete_batch就形成了一个嵌套触发器,下边来验证嵌套触发器的不错。 Course表中的数据如图所示
997755.com澳门葡京 61
Teacher_course表中的数据如图所示
997755.com澳门葡京 62
Course_selection**表中的数据如图所示
997755.com澳门葡京 63
以课程0013为例,执行下列语句

DELETE FROM course WHERE course_id='0013'

Course表的数目如图所示
997755.com澳门葡京 64
Teacher_course表的数码如图所示
997755.com澳门葡京 65
Course_selection表的数额如图所示
997755.com澳门葡京 66
有着关于0013学科的多寡都被剔除。嵌套触发器有效。

注:在触发器teacher_course_delete_batch中,我额外参加了一个断定,当teacher_course表中还有老师在执教这门课程时,所有有关这门学科的学童选课信息都反对删除。这样做在嵌套触发器里是多余的,删除一门课程,必然会去除teacher_course表中负有与这门课程有关的笔录,也必将删除course_selection表中有所与这门课程有关的笔录,然则,这样做可以保证该触发器可以单独于嵌套触发器被单独激活。Teacher_course_delete_batch触发器仍是可以用来此外嵌套触发器中,看示例12

示例12:有teacher表(讲师信息表),teacher_course(讲师所助教程表),和course_selection表(学生选课记录表),写一个嵌套触发器,实现当一个教授离职时,在剔除该老师所教课程音讯,假如没有老师教这门科目,再删除该科目选课记录。
其中teacher_course表的触发器teacher_course_delete_batch已经在示例11中写完,只需创立teacher表的teacher_delete_batch触发器即可
实践下列代码

CREATE TRIGGER teacher_delete_batch
ON teacher
FOR DELETE
AS
DECLARE @teacher_id CHAR(4)
DECLARE teacher_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT teacher_id FROM deleted
OPEN teacher_cursor
FETCH NEXT FROM teacher_cursor INTO @teacher_id
WHILE @@FETCH_STATUS=0
BEGIN
DELETE FROM teacher_course WHERE teacher_id=@teacher_id
FETCH NEXT FROM teacher_cursor INTO @teacher_id
END
GO

测试嵌套触发器的正确
Teacher表的数目如图所示
997755.com澳门葡京 67
Teacher_course表的数码如图所示
997755.com澳门葡京 68
Course_selection表的数额如图所示
997755.com澳门葡京 69
以删除0012号讲师路易为例,0012号教授讲课0013号课程,且teacher_course表中并无其他讲师执教0013号课程,按照逻辑要刨除teacher_course表中0012号教授的所教课程记录和course_selection表中兼有0013号课程的选课记录。执行下列语句

DELETE FROM teacher WHERE teacher_id='0012'

Teacher表的数目如图所示
997755.com澳门葡京 70
Teacher_course表的数码如图所示
997755.com澳门葡京 71
Course_selection表的数额如图所示
997755.com澳门葡京 72
测试结果正确
参照上边的数量,继续测试另一种状态,以删除0011号教授卢含笑为例,0011号教授讲课0012号课程,在teacher_course表中还有任何导师执教该课程,由此嵌套触发器会删除teacher_course表中关于0011号教授教学课程记录,但不会去除course_selection表中有关0012号课程的选课记录。执行下列语句

DELETE FROM teacher WHERE teacher_id='0011'
GO

结果如图所示
997755.com澳门葡京 73
Teacher表的数据如图所示
997755.com澳门葡京 74
Teacher_course表的数量如图所示
997755.com澳门葡京 75
Course_selection表的数目如图所示
997755.com澳门葡京 76

        确立触发器

1.3.3.2.查看触发器嵌套的层数

可以应用@@NESTLEVEL全局变量来查看当前触发器嵌套的层数
示例13:在示例11teacher_course_delete_batch触发器中运用@@NESTLEVEL全局变量查看当前触发器嵌套的层数
执行下列语句修改teacher_course_delete_batch触发器

ALTER TRIGGER teacher_course_delete_batch
ON teacher_course
FOR DELETE
AS
DECLARE @course_id CHAR(4)
DECLARE teacher_course_cursor CURSOR LOCAL FORWARD_ONLY
FOR SELECT DISTINCT course_id FROM deleted
OPEN teacher_course_cursor
FETCH NEXT FROM teacher_course_cursor INTO @course_id
WHILE @@FETCH_STATUS=0
BEGIN
IF (SELECT COUNT(*) FROM teacher_course WHERE course_id=@course_id)=0
DELETE FROM course_selection WHERE course_id=@course_id
ELSE
PRINT 'course_id为'+@course_id+'的课程依然正常开课,该课程的学生选课情况不予删除'
FETCH NEXT FROM teacher_course_cursor INTO @course_id
SELECT @@NESTLEVEL AS NESTLEVEL
END
GO

测试teacher_course_delete_batch触发器(数据就不看了,未影响触发器原来的功用)
进行下列语句

DELETE FROM teacher_course WHERE teacher_id='0009'
--直接在teacher_course表中删除,激活teacher_course_delete_batch触发器

结果如图所示
997755.com澳门葡京 77
履行下列语句

DELETE FROM teacher WHERE teacher_id='0009'
--在teacher表中删除,触发teacher_delete_batch触发器,进而触发teacher_course_delete_batch触发器

结果如图所示
997755.com澳门葡京 78

1 CREATE TRIGGER 触发器名称
2 ON 表名
3 { FOR | AFTER | INSTEAD OF } 
4 { [ INSERT ] [ , ] [ DELETE ] [ , ] 
5    [UPDATE ] }
6 AS 
7   SQL 语句 [ ... n ] 

1.3.3.3.禁用和启用嵌套触发器

EXEC sp_configure 'nested triggers',0;
GO
--禁用嵌套触发器
EXEC sp_configure 'nested triggers',1;
GO
--启用嵌套触发器

        **去除触发器:**

1.3.4.递归触发器

 

1.3.4.1.递归触发器

触发器被激活,更改了表中数量,这种变动又激活了它和谐,这种触发器被叫作递归触发器。数据库创设时默认递归触发器禁用。但足以使用ALTER
DATABASE
拔取来启用它。递归触发器启用的先决条件是嵌套触发器必须是启用情状,如果嵌套触发器禁用,不管递归触发器的安排是什么样都将被剥夺。而在递归触发器中,inserted表和deleted表都只包含被上五遍触发器影响的行数据。
递归触发器有以下二种不同门类(这边没有适合的运用示范可举,先不举例了)

1 DROP TRIGGER 触发器名 [ , ... n ]

1.3.4.2.一直递归

直白递归触发器是指任何递归过程只有它自己一个触发器的参加。自己激活了友好。

 

1.3.4.3.直接递归

直接递归触发器是指任何递归过程有六个触发器参与,例如A激活B,B激活C,C激活A。能够当做是递归和嵌套的结合。
利用递归触发器时需要小心以下几点:
递归触发器很复杂,需要通过有系统的计划和完美测试
在任意点的数码修改都会激活递归触发器。只好按触发器被激活的特定顺序更新表。
拥有触发器一起构成一个大事务,任意触发器的随意地方上的ROLLBACK言辞都将撤消所有数据的输入,所有数据均被擦除。
触发器最四只好递归16层,一旦有第17个触发器出席进去,结果与ROLLBACK指令一样,所有数据都将被擦除

          修改触发器:

1.3.4.4.启用递归触发器

可以采取SQL Server 2008的管理器工具来启用递归触发器。
997755.com澳门葡京 79

 

1.4.管制触发器

剥夺和启用触发器
履行下列语句禁用和启用触发器

ALTER TABLE student DISABLE TRIGGER update_stu_no_single
--禁用update_stu_no_single触发器
GO
ALTER TABLE student ENABLE TRIGGER update_stu_no_single
--启用update_stu_no_single触发器
GO

施行下列语句禁用和启用数据库级别触发器

DISABLE TRIGGER deny_DDL_table ON DATABASE
--禁用数据库级别触发器deny_DDL_table
GO
ENABLE TRIGGER deny_DDL_table ON DATABASE
--启用数据库级别触发器deny_DDL_table
GO
1 ALTER TRIGGER 触发器名称
2 ON 表名
3 { FOR | AFTER | INSTEAD OF } 
4 { [ INSERT ] [ , ] [ DELETE ] [ , ] 
5    [UPDATE ] }
6 AS 
7   SQL 语句 [ ... n ] 

 

          打开和剥夺:

 

1 disable trigger trigDB on database --禁用触发器
2 enable trigger trigDB on database --开启触发器

 

          提示和保安:

 

1 print '删除了触发器***' 
2 raiserror('数据一致性验证',16,1)
3 rollback transaction 

 

示例

 

    在S表创建UPDATE触发器:

1 Create trigger tri_Updates
2 on s
3 for update 
4 as 
5 print 'the table s was updated'

 

    不准删除SC表中成绩没有格学生的记录:

1 CREATE TRIGGER tri_del_grade
2   ON SC FOR DELETE
3   AS
4     IF EXISTS(SELECT * FROM DELETED    
5           WHERE Grade < 60)
6       ROLLBACK 

 

   禁止将SC表中不及格学生的战绩改为合格:

 1 create trigger tri_update_grade
 2 on sc for update
 3 as 
 4   if update(grade)
 5   if exists(select * from inserted,deleted
 6   where inserted.sno=deleted.sno and inserted.grade>=60 and deleted.grade<60)
 7   begin    
 8     print '不能将不及格的成绩改为及格'
 9   rollback
10   end

 

相关文章

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*
*
Website