触发器的定义触发器是SQL Server提供给程序员和数据分析师的一种确保数据完整性的方法。它是一个与表事件相关的特殊存储过程。它的执行不是由程序调用或手动启动,而是由事件
触发器是SQL Server提供给程序员和数据分析师的一种确保数据完整性的方法。它是一个与表事件相关的特殊存储过程。它的执行不是由程序调用或手动启动,而是由事件触发。例如,当一个表被操作(插入、删除、更新)时,它将被激活执行。
触发器的功能
触发器的主要作用是可以实现主键和外键无法保证的复杂参照完整性和数据一致性,可以级联修改数据库中的相关表,提高比CHECK约束更复杂的数据完整性,自定义错误消息。
触发器的主要功能如下
强制数据库间的引用完整性级联修改数据库中所有相关的表,自动触发其它与之相关的操作跟踪变化,撤销或回滚违法操作,防止非法修改数据返回自定义的错误消息,约束无法返回信息,而触发器可以触发器可以调用更多的存储过程
触发器的优点
触发器是自动的。当对表中的数据做了任何修改之后立即被激活。触发器可以通过数据库中的相关表进行层叠修改。触发器可以强制限制。这些限制比用CHECK约束所定义的更复杂。与CHECK约束不同的是,触发器可以引用其他表中的列。
触发器的分类SQL Server包括三种常规类型的触发器:DML触发器、DDL触发器和登录触发器。
DML(数据操作语言)触发器
DML触发器是附加到特定表或视图的一些操作码,当数据库服务器中发生数据操作语言事件时执行这些操作码。
SQL Server中有三种类型的DML触发器:
INSERT触发器:向表中插入数据时被触发;DELETE触发器:从表中删除数据时被触发;UPDATE触发器:修改表中数据时被触发。
当您遇到以下情况时,应该考虑使用DML触发器:
通过数据库中的相关表实现级联更改防止恶意或者错误的INSERT、DELETE和UPDATE操作,并强制执行CHECK约束定义的限制更为复杂的其他限制。评估数据修改前后表的状态,并根据该差异才去措施。
DDL(数据定义语言)触发器
当服务器或数据库中发生数据定义语言(主要是以CREATE、DROP和ALTER开头的语句)事件时,将激活并使用DDL触发器。使用DDL触发器可以防止对数据架构的某些更改,或者记录数据中的更改或事件操作。
登录触发器
登录触发器触发存储过程以响应登录事件。当与SQL Server实例建立用户会话时,会引发此事件。登录触发器将在登录的身份验证阶段完成之后、用户会话实际建立之前触发。因此,来自触发器内部并通常到达用户的所有消息(如错误消息和来自PRINT语句的消息)都将被传输到SQL Server错误日志。如果身份验证失败,将不会触发登录触发器。
触发器的工作原理
触发时:
系统自动在内存中创建
INSERTED
表或
DELETED
表;只读,不允许修改,触发器执行完成后,自动删除。
插入的表:
临时保存了插入或更新后的记录行;可以从INSERTED表中检查插入的数据是否满足业务需求;如果不满足,则向用户发送报告错误消息,并回滚插入操作。
已删除的表:
临时保存了删除或更新前的记录行;可以从DELETED表中检查被删除的数据是否满足业务需求;如果不满足,则向用户报告错误消息,并回滚插入操作。
插入的表和删除的表之间的比较:
创建触发器
创建触发器的语法:
在T-SQL语句中,在table _ name上为| after |而不是[delete,insert,update]创建触发器trigger _ name带加密]
注:
WITH ENCRYPTION表示由加密触发器定义的SQL文本。
删除、插入、更新指定触发器的类型。
触发器的示例
创建学生表
create table student( stu_id int identity(1,1) primary key, stu_name varchar(10), stu_gender char(2), stu_age int)
创建插入触发器--创建INSERT触发器create trigger trig_inserton student after insertasbegin --判断student_sum表是否存在 if object_id(N'student_sum',N'U') is null --创建存储学生人数的student_sum表 create table student_sum( stuCount int default(0) ); 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;
执行上述语句后,结果如下图所示:
由于学生总数表student_sum表被定义为在向学生表中插入数据后计算学生总数,所以学生总数表应该禁止用户向其中插入数据。
--创建insert_forbidden,禁止用户向student_sum表中插入数据create trigger insert_forbiddenon student_sum after insertasbegin RAISERROR('禁止直接向该表中插入记录,操作被禁止',1,1) --raiserror 是用于抛出一个错误 rollback transactionend--触发触发器insert_forbiddeninsert student_sum (stuCount) values(5);
结果如下:
创建删除触发器
当用户执行删除操作时,删除触发器将被激活,从而控制用户从数据库中删除数据记录。删除触发器触发后,用户删除的记录将被添加到删除表中,原表的相应记录也将被删除,因此可以在删除表中查看删除的记录。
--创建delete触发器create trigger trig_deleteon student after deleteasbegin select stu_id as 已删除的学生编号, stu_name stu_gender, stu_age from deletedend;--执行一条delete语句触发trig_delete触发器delete from student where stu_id=1;
结果如下:
创建更新触发器
当用户对指定的表执行UPDATE语句时,将调用UPDATE触发器。这种类型的触发器用于限制用户对数据的修改。更新触发器可以执行两个操作:更新前的记录存储在删除的表中,更新后的记录存储在插入的表中。
--创建update触发器create trigger trig_updateon student after updateasbegin 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;
结果如下:
创建替代触发器
与上面提到的三个AFTER触发器不同,SQL Server服务器在执行AFTER触发器的SQL代码后,首先建立临时插入表和删除表,然后在代码中执行数据库操作,最后激活触发器中的代码。至于INSTEAD OF触发器,SQL Server在执行触发INSTEAD OF触发器的代码时,首先建立临时插入表和删除表,然后直接触发INSTEAD OF触发器,拒绝执行用户输入的DML操作语句。
--创建instead of触发器 create trigger trig_insteadOfon student instead of insertas begin declare @stuAge int; select @stuAge=(select stu_age from inserted) if(@stuAge >120) select '插入年龄错误' as '失败原因'end
创建、执行插入语句来触发trig_insteadOf触发器
批注
触发器经常用在早期的数据处理中,尤其是在处理一些由于某些动作而需要调整其他表的逻辑时。但是,随着数据量的增加,触发器对数据库性能的影响越来越大,容易造成数据库性能下降。所以触发器是禁止在数据量大的场景下使用的,但是它的逻辑处理功能却被保留了下来,说明它还有很深的应用场景,我们需要掌握它的相关用法。