触发器总结
触发器的总结:
触发器是一种特殊的存储过程,其特殊性在于它并不需由用户来直接调用,当对表进行插入、修改、删除操作时自动执行。所以,触发器可以用来实施复杂的完整性约束。
触发器的优点:
1.可实现数据库中多张表的级联更新。
2.实现比CHECK约束更为复杂的约束。使用CHECK约束,可以限制不满足检查条件的记录输入表中。CHECK约束的检查条件表达式不允许引用其它表中的字段,而触发器可引用其它表中的字段。
触发器的触发方式:
AFTER或FOR 关键字指定 后触发:当引起触发器执行的更新语句执行完成,并通过各种约束检查后,才执行后触发,这种触发方式称做后触发
INSTEAD OF 关键字指定 替代触发:引起触发器执行的更新语句停止执行,仅执行触发器语句,这种触发方式称做替代触发
inserted临时表和deleted临时表:
每个触发器被激活时,系统都会为它自动创建两个临时表: inserted表和deleted表。这两个表的结构总是与激活触发器的表的结构相同,触发器执行完成后,与该触发器相关的这两个临时表也会被自动删除。
在执行DELETE语句删除表中的数据时,系统将数据从表中删除的同时,自动把删除的数据插入到deleted这一系统临时表中;当执行INSERT语句向表中插入数据时,系统将数据插入表的同时,也把相应的数据插入到inserted这一系统临时表中;在执行UPDATE语句修改表数据时,系统先从表中删除表中原有的行,然后再插入新行。其中被删除的行存放在deleted表中,同时插入的新行存放在inserted表中。
注意:
1.CREATE TRIGGER语句必须是一个批处理中的第一条语句。
2.触发器只能在当前的数据库创建,但触发器可能引用其它数据对象。
3.如果指定触发器所有者名限定触发器,要以相同方式限定表名。
4.在同一CREATE TRIGGER语句中,可以为多种操作定义相同的触发器操作。
5.如果一个表的外键在DELETE、UPDATE操作上定义了级联,则不能在该表上定义INSTEAD OF DELETE、INSTEAD OF UPDATE触发器。
6.所有建立和修改数据库及其对象的语句、所有DROP语句都不允许在触发器使用。
7.触发器不返回任何结果,为了阻止从触发器返回结果,不要在触发器定义中包含SELECT语句或变量赋值。如果必须在触发器中进行变量赋值,则应该在触发器的开头使用SET NOCOUNT ON语句以避免返回任何结果集。
完整形式:
1. 语法格式
CREATE TRIGGER trigger_name ON { table | view } /*指定触发器名及操作对象*/
[ WITH ENCRYPTION ] /*说明是否采用加密方式*/
{ FOR | AFTER | INSTEAD OF } { [DELETE] [,] [INSERT] [,] [UPDATE] }
/*定义触发器的类型*/
[ NOT FOR REPLICATION ] /*说明该触发器不用于复制*/
AS
[ { IF UPDATE ( column ) [ { AND | OR } UPDATE ( column ) ]
[ ...n ]
| IF ( COLUMNS_UPDATED ( ) { bitwise_operator } updated_bitmask )
{ comparison_operator } column_bitmask [ ...n ]
} ] /*两个IF子句用于说明触发器执行的条件*/
sql_statements /* T- SQL语句序列*/
============
后触发:
==========
例15.1 对于school数据库,如果在student表中添加或更改数据,则向客户端显示一条信息。
USE XSBOOK
IF EXISTS (SELECT name FROM sysobjects
WHERE name = 'reminder' AND type = 'TR')
DROP TRIGGER reminder
GO
CREATE TRIGGER reminder ON student
FOR INSERT, UPDATE
AS RAISERROR (13001, 16, 10) /*使用带有提示消息的触发器*/
GO
-------------------
例15.2 在数据库school中创建一触发器,当向score表中插入一记录时,检查该记录的sno在student表是否存在,检查cno号在course表中是否存在,若有一项为否,则不允许插入,并返回“数据不一致”错误信息。
CREATE TRIGGER TR_score ON score
FOR INSERT
AS
IF NOT EXISTS(SELECT * FROM student WHERE sno =(SELECT sno FROM inserted)) OR
NOT EXISTS(SELECT * FROM course WHERE cno =(SELECT cno FROM inserted))
BEGIN
RAISERROR('数据不一致',16,1)
ROLLBACK TRANSACTION
END
---------------
例15.3 在school数据库的score表上创建一触发器,若对sno列和cno列修改,则给出提示信息,并取消修改操作,用两种方法实现。
CREATE TRIGGER TR1_score ON score
FOR UPDATE
AS
IF UPDATE(sno) OR UPDATE(cno)
BEGIN
RAISERROR('不允许修改',16,1)
ROLLBACK TRANSACTION
END
====================
INSTEAD OF 触发器
====================
CREATE VIEW VIEW2 /*替换触发器可用于试图*/
AS
SELECT sno,sname,ssex,sbirthday,class
FROM student
CREATE TRIGGER INSTEADOFTR_VIEW2 ON VIEW2
INSTEAD OF INSERT
AS
BEGIN
INSERT INTO student(sno,sname,class)
SELECT sno,sname,class FROM inserted
END
--------------------
向score表插入一条学生选课记录,如果该记录学生成绩低于60分,则把他成绩改为60分。
CREATE TRIGGER S1 ON score /*用For形式实现*/
FOR INSERT
AS
BEGIN
DECLARE @num1 char(5),@num2 char(10)
IF (SELECT degree FROM inserted)<60
BEGIN
SET @num1=(SELECT sno FROM inserted)
SET @num2=(SELECT cno FROM inserted)
UPDATE score SET degree=60 WHERE sno=@num1 AND cno=@num2
END
END
CREATE TRIGGER S1 ON score /*用替换触发器 实现*/
INSTEAD OF INSERT
AS
BEGIN
DECLARE @num1 char(10),@num2 char(10)
IF (SELECT degree FROM inserted)<60
BEGIN
SET @num1=(SELECT sno FROM inserted)
SET @num2=(SELECT cno FROM inserted)
INSERT INTO score VALUES(@num1,@num2,60)
END
END
INSERT INTO SC VALUES('95001','5',50)
INSERT INTO SC VALUES('95001','6',99)