您的位置:首页 > 数据库

SQL Server 触发器

2015-04-12 00:40 141 查看
触发器是一种特殊类型的存储过程,它不同于之前的我们介绍的存储过程。触发器主要是通过事件进行触发被自动调用执行的。而存储过程可以通过存储过程的名称被调用。

Ø什么是触发器

触发器对表进行插入、更新、删除的时候会自动执行的特殊存储过程。

触发器一般用在check约束更加复杂的约束上面。

与普通的存储过程的区别是:当对某一个表进行操作。诸如:update、insert、delete这些操作的时候,系统会自动调用执行该表上对应的触发器

SQLServer2005中触发器可以分为两类:DML触发器和DDL触发器,其中DDL触发器会影响多种数据定义语言语句而激发,这些语句有create、alter、drop语句。

DML触发器分为:

1、after触发器(之后触发)

a、insert触发器

b、update触发器

c、delete触发器

2、insteadof触发器(之前触发)

其中after触发器要求只有执行某一操作insert、update、delete之后触发器才被触发,且只能定义在表上。而insteadof触发器表示并不执行其定义的操作(insert、update、delete)而仅是执行触发器本身。既可以在表上定义insteadof触发器,也可以在视图上定义。

触发器有两个特殊的表:插入表(instered表)和删除表(deleted表)。这两张是逻辑表也是虚表。系统在内存中创建这两张表,不会存储在数据库中。而且两张表的都是只读的,只能读取数据而不能修改数据。这两张表的结果总是与被改触发器应用的表的结构相同。当触发器完成工作后,这两张表就会被删除。Inserted表的数据是插入或是修改后的数据,而deleted表的数据是更新前的或是删除的数据。
对表的操作
Inserted逻辑表
Deleted逻辑表
增加记录(insert)存放增加的记录
删除记录(delete)存放被删除的记录
修改记录(update)存放更新后的记录存放更新前的记录
Update数据的时候就是先删除表记录,然后增加一条记录。这样在inserted和deleted表就都有update后的数据记录了。注意的是:触发器本身就是一个事务,所以在触发器里面可以对修改数据进行一些特殊的检查。如果不满足可以利用事务回滚,撤销操作。

Ø触发器语法及示例

--创建触发器语法

createtriggertgr_name

ontable_name

withencrypion//加密触发器

forupdate...

as


--创建insert插入类型触发器

createtriggertgr_classes_insert

onclasses

forinsert//插入触发

as

--定义变量

declare@idint,

@namevarchar(20),

@tempint;

--在inserted表中查询已经插入记录信息

select@id=id,@name=namefrominserted;

set@name=@name+convert(varchar,@id);

set@temp=@id/2;

insertintostudentvalues(@name,18+@id,@temp,@id);

print'添加学生成功!';

go

--向classes表插入数据

insertintoclassesvalues('5班',getDate());

--查询数据,insert触发器会在student表中添加一条记录。

select*fromclasses;

select*fromstudentorderbyid;


--delete删除类型触发器

createtriggertgr_classes_delete

onclasses

fordelete//删除触发

as

print'备份数据中……';

if(object_id('classesBackup','U')isnotnull)

--存在classesBackup,直接插入数据

insertintoclassesBackupselectname,createDatefromdeleted;

else

--不存在classesBackup创建再插入

select*intoclassesBackupfromdeleted;

print'备份数据成功!';

go

--不显示影响行数

setnocounton;

deleteclasseswherename='5班';

--查询数据,delete触发器会在删除数据的时候,将刚才删除的数据保存在deleted表中。

select*fromclasses;

select*fromclassesBackup;


--update更新类型触发器

createtriggertgr_classes_update

onclasses

forupdate

as

declare@oldNamevarchar(20),

@newNamevarchar(20);

--更新前的数据

select@oldName=namefromdeleted;

if(exists(select*fromstudentwherenamelike'%'+@oldName+'%'))

begin

--更新后的数据

select@newName=namefrominserted;

updatestudentsetname=replace(name,@oldName,@newName)wherenamelike'%'+@oldName+'%';

print'级联修改数据成功!';

end

else

print'无需修改student表!';

go

--查询数据,update触发器会在更新数据后,将更新前的数据保存在deleted表中,更新后的数据保存在inserted表中。

select*fromstudentorderbyid;

select*fromclasses;

updateclassessetname='五班'wherename='5班';





--update更新列级触发器(将范围缩小到列)

createtriggertgr_classes_update_column

onclasses

forupdate

as

--列级触发器:是否更新了班级创建时间

if(update(createDate))

begin

raisError('系统提示:班级创建时间不能修改!',16,11);

rollbacktran;

end

go

--测试,更新列级触发器可以用update判断是否更新列记录

select*fromstudentorderbyid;

select*fromclasses;

updateclassessetcreateDate=getDate()whereid=3;//会回滚

updateclassessetname='四班'whereid=7;





--insteadof触发器并不执行其定义的操作(insert、update、delete),而仅是执行触发器本身的内容。

--创建语法

createtriggertgr_nameontable_name

withencryption

insteadofupdate...

as



--创建insteadof触发器

createtriggertgr_classes_inteadOf

onclasses

insteadofdelete/*,update,insert*/

as

declare@idint,@namevarchar(20);

--查询被删除的信息并赋值

select@id=id,@name=namefromdeleted;

print'id:'+convert(varchar,@id)+',name:'+@name;

--先删除student的信息

deletestudentwherecid=@id;

--再删除classes的信息

deleteclasseswhereid=@id;

print'删除[id:'+convert(varchar,@id)+',name:'+@name+']的信息成功!';

go

--测试

select*fromstudentorderbyid;

select*fromclasses;

deleteclasseswhereid=7;


--显示自定义消息raiserror

createtriggertgr_message

onstudent

afterinsert,update

as

raisError('tgr_message触发器被触发',16,10);

go

--测试

insertintostudentvalues('lily',22,1,7);

updatestudentsetsex=0wherename='lucy';

select*fromstudentorderbyid;


--修改触发器

altertriggertgr_message

onstudent

afterdelete

as

raisError('tgr_message触发器被触发',16,10);

go

--测试

deletefromstudentwherename='lucy';


--禁用触发器

disabletriggertgr_messageonstudent;

--启用触发器

enabletriggertgr_messageonstudent;


--查询已存在的触发器

select*fromsys.triggers;

select*fromsys.objectswheretype='TR';


--查看触发器触发事件

selectte.*fromsys.trigger_eventste

joinsys.triggerstont.object_id=te.object_id

wheret.parent_class=0andt.name='tgr_valid_data';


--查看创建触发器语句

execsp_helptext'tgr_message';



/*完整示例,验证插入数据*/

if((object_id('tgr_valid_data','TR')isnotnull))

droptriggertgr_valid_data

go

createtriggertgr_valid_dataonstudent

afterinsert

as

declare@ageint,

@namevarchar(20);

select@name=s.name,@age=s.agefrominserteds;

if(@age<18)

begin

raisError('插入新数据的age有问题',16,1);

rollbacktran;

end

go

--测试

insertintostudentvalues('forest',2,0,7);

insertintostudentvalues('forest',22,0,7);

select*fromstudentorderbyid;




/*完整示例,操作日志*/

if(object_id('log','U')isnotnull)

droptablelog

go

createtablelog(

idintidentity(1,1)primarykey,

actionvarchar(20),

createDatedatetimedefaultgetDate()

)

go

if(exists(select*fromsys.objectswherename='tgr_student_log'))

droptriggertgr_student_log

go

createtriggertgr_student_logonstudent

afterinsert,update,delete

as

if((exists(select1frominserted))and(exists(select1fromdeleted)))

begin

insertintolog(action)values('updated');

end

elseif(exists(select1frominserted)andnotexists(select1fromdeleted))

begin

insertintolog(action)values('inserted');

end

elseif(notexists(select1frominserted)andexists(select1fromdeleted))

begin

insertintolog(action)values('deleted');

end

go

--测试

insertintostudentvalues('king',22,1,7);

updatestudentsetsex=0wherename='king';

deletestudentwherename='king';

select*fromlog;

select*fromstudentorderbyid;

http://www.cnblogs.com/SkySoot/archive/2012/04/10/2441355.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: