码迷,mamicode.com
首页 > 数据库 > 详细

4. SQL -- 触发器

时间:2015-03-19 06:34:04      阅读:261      评论:0      收藏:0      [点我收藏+]

标签:create   触发器   update   影响   

触发器

触发器是一类特殊的存储过程.它与表的关系密切,用于保护表中的数据,当有操作影响到触发器保护的数据时,触发器自动执行,例如使用触发器实现多个表间数据的一致性.

一般情况下,对表数据的操作有插入,修改,删除,因而维护数据的触发器也可分为三类:

INSERT,UPDATEDELETE

一、使用SQL命令创建触发器

语法格式如下:

Create trigger tigger_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_update(){ bitwise_operator } updated_bitmask)

{comparison_operator } column_bitmask [..n]}]   --两个if语句用来说明触发器执行的条件

Sql_statement […n]                                                          --一条或若干条sql语句

}}

        说明:

(1)     Table | view指在其上执行触发器的表或视图

(2)     After关键字用于说明触发器在指定操作都成功执行后触发,after是默认设置,不能在视力上定义after触发器

(3)     If update(column)子句用于测试在指定的列上(column)上进行的insertupdate操作不能用于delete操作,返回值为truefalse

(4)     If(columns_update())子句用于测试是否插入或更新了指定的列,返回二进制位数据,若为0没有成功更新,若为1,更新成功

(5)     Bitwise_operator为用于比较去处的位运算符.update_bitmask的值为整型的位屏蔽码,与实际更新或插入的列对应.例如表t 包含列C0,C1,C2,C3C4.假定该表上有update触发器,若要检查列C0,C2,C4是否都有更新,可指定update_bitmask的值为00010101(0x15);若要检查是否只有列C1有更新,可指定updated_bitmask的值为00000010

(6)     Comparison_operator为比较运算符;columns_bitmask为列屏蔽友,用来检查是否已更新或插入对应列

(7)     Sql_statement为触发器的SQL语句,当执行delete,insertupdate,对应的解发器生效.

(8)     N表示触发器可包含多条SQL语句

触发器中使用的特殊表

    执行触发器时,系统创建了两个特殊的逻辑表:inserted表和deleted

         Inserted:当向表中插入数据时.insert触发器触发执行,新的记录插入到触发器表和inserted表中

         Deleted:用于保存已从表中删除的记录,当触发一个delete触发器时,被删除的记录存放到deleted表中

    修改一条记录等于插入一条新记录,同时删除旧记录.对定义了update触发器的表记录修改时,表中原记录移到deleted表中,修改过的记录插入到inserted表中,触发器可检查deletedinserted

    :检索deleted,inserted表中的所有记录

                   Select * from deleted

                   Select * from inserted

使用触发器的限制

(1)     Create trigger必须是批处理中的第一条语句,并且只能应用到一个表中

(2)     触发器只能在当前的数据库中创建,但触发器可以引用当前数据库的外部对象

(3)     如果指定触发器所有者名限定触发器,要以相同的方式限定表名

(4)     在同一create trigger语句中,可以为多种操作(insertupdate)定义相同的触发器操作

(5)     如果表中存在外键,不能定义insertupdate触发器

(6)     触发器中可指定set语句,执行期间有效,执行完恢复到以前的状态

(7)     触发器中不能指定如下T-SQL语句:

Create database,alter database,load database,restore database,drop database,load log,restore log,disk init,disk resizereconfigure

(8)     触发器不能有任何结果集返回

举例

对于student数据库,如果在student_table表中添加或更改数据,则将向客户端显示一条信息

/*使用带有提示消息的触发器

USE master

GO

EXEC sp_addmessage 50021, 10, ‘no update or delete‘,‘us_english‘,false,replace

EXEC sp_addmessage 50021, 10, ‘不能插入或更新‘,‘简体中文‘,false,replace

go

Use student

If exists(select name from sysobjects where name=’reminder’ and type=’tr’)

           Drop trigger reminder

Go

Create trigger reminder on student_table

           For insert,update

           As raiserror(4008,16,10)

消息4008sysmessages中的用户定义消息,有关创建用户消息的方法看下sp_addmessage存储过程

注意:SQL server 在调用sp_addmessage 有一个参数@lang是用来指明所需要加入的message的语种的,如果没有指定,则认为是语言是会话的默认语言,如果你安装的是中文版,则一般是中文,而SQL server有强制必须先增加英文的错误信息之后才能增加中文的错误信息,所以必须现增加英文版的错误信息。然后再增加本地语种的错误信息。

使用sp_dropmessag删除sysmessages表中添加的信息。直接delete删除不掉

例如:use master go exec sp_dropmessage 50021

(1)     在数据库student中创建一个触发器,当向student_course_table中插入一记录时,检查该记录的学号在student_table表中是否存在,检查课程号在course_table中是否存在,若都有则插入,否则不执行插入

Use student

If object_id(‘check_trig‘) is not null

           Drop trigger check_trig

Go

Create trigger check_trig on student_course_table

For insert

As

If exists(select *

           from inserted a

           Where a.studentID not in(select b.studentID from student_table b) or

           a.courseID not in(select c.courseID from course_table c))

           Begin

                    Raiserror(‘违背数据的一致性‘,16,1)

                    Rollback transaction

           End

(2)     student数据库的student_course_table表中创建一个触发器,若对学号列和课程列修改,则给出提示信息,并取消修改操作.

通过调用colunms_updated()函数,可快速测试对学号列和课程号列修改所做的更改

Use student

Go

Create trigger update_trig

           On student_course_table

           For update

As

If(columns_updated() &3)>0

           Begin

                    Raiserror(‘违背数据的一致性’,16,1)

                    Rollback transaction

           End

Go

(3)     Inserted of触发器的设计

如果视图的数据来自于多个基表,则必须使用instead of 触发器支持引用表中数据的插入,更新和删除操作

例如:若在一个多表视图上定义了instead of insert触发器,那视图的值可能允许为空,也可能不为空,若视图某列的值不允许为空,inset语句必须为该列提供相应的值.

     如果视图的列为以下几种情况之一:

1>     基表中的计算列

2>     基表中的标识列

3>     具有timestamp数据类型的基表列

该视图的insert语句必须为这些列指定值,instead of 触发器在构成将值插入基表的insert语句时会指定的值

:student数据库中的创建表,视图和触发器,以说明instead of insert触发器的使用

Use student

go

Create table books

(

bookKey int identity(1,1),

bookName varchar(10) not null,

color varchar(10) not null,

computedCol as (bookName + color),

Page int,

)

Go

--创建一个视图,包含基表中的所有列

Create view view2

As

Select * from books

Go

--view2视图上创建一个instead of insert触发器

Create trigger insteadTrig on view2

Instead of insert

As

Begin

           Insert into books

           Select bookName,color,page from inserted

End

Go

直接引用books表的insert语句不能为bookKey字段和computedCor字段提供值

--正确的insert语句

Insert into books(bookName,color,page)

           Values(‘计算机‘,‘红色‘,100)

--查看结果

select * from books

2计算机红色    计算机红色     100 

--不正确的insert语句(就是插入所有列)

Insert into books values(2,‘计算机辅助教程‘,‘红色‘,‘绿色‘,100)

但对于引用view2视力的insert语句为每一列都指定值:例如

--对于view2正确的insert语句 

Insert into view2 values(2,‘计算机‘,‘红色‘,‘绿色‘,100)

--查看结果

Select * from view2

2计算机红色    计算机红色     100 

3计算机红色    计算机红色     100 

在执行视图的插入语句时,虽然将bookKeycomputedCor字段的值传递了insertedTrig触发器中,但触发器中的insert语句没有选择inserted表的中bookKeycomputedCol字段的值(即你写入的这两个字段的值并不真正插入的,它是由系统自动生成或是计算列) 

    :删除触发器

        利用SQL语句琰删除触发器

                    Drop trigger trigger_name[…n]


本文出自 “Ricky's Blog” 博客,请务必保留此出处http://57388.blog.51cto.com/47388/1622003

4. SQL -- 触发器

标签:create   触发器   update   影响   

原文地址:http://57388.blog.51cto.com/47388/1622003

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!