触发器

基本概念

1.触发器的概念

触发器是在满足某个特定条件自动触发执行的专用存储过程,用于保证表中的数据遵循数据库设计者确定的规则和约束。触发器可以用SQL语句编写。与存储过程不同的是,存储过程是通过名称而被显式调用执行,而触发器是通过事件进行触发而被执行,不能被显式调用。如当对表进行更新(update),插入(insert),删除(delete)时,DBMS就会自动触发执行触发器所定义的SQL语句。
SQL Server中提供两种触发器:after触发器和instead of触发器。

2.触发器中的两个特殊表

inserted和deleted表。这两个表存储在缓存中,由系统维护,不允许用户对其修改。

(1)inserted表。该表中存放的是由于执行insertupdate语句而要向表中插入的新数据行。当用户执行insertupdate时,新的数据行被添加到激活触发器的表中,同时这些数据行的备份被复制到insertd临时表中。
(2)deleted表。该表中存放的是由于执行deleteupdate语句而要从表中删除的数据行。在执行deleteupdate语句时,指定的数据行被用户从基本表中删除,然后被转移到了deleted表中。一般来说,在基本表和deleted表中不会存在有相同的数据行。
   对于表的更新操作update,可以看作是由两个操作组成的。首先将旧的数据行从基本表中转移到deleted表中,即执行一个delete操作;然后将新的数据行同时插入到激活触发器的基本表和inserted表中。

定义触发器

1.使用SQL语句创建触发器

create trigger trigger_name on {table_name | view_name}
[with encryption] {for | after | instead of}
[insert,update,delete]
as
  sql_statement
其中
trigger_name:用户创建的触发器的名称。触发器名称必须符合标识符规则,并且在数据库中必须唯一。
table_name | view_name:在其上定义触发器的表或视图名称,也称为触发器表或触发器视图
with encryption:加密syscomments表中包含的create trigger语句文本。
after:指定触发器的激活时机是在触发SQL语句中指定的操作都已成功执行后。一个表的每个修改动作均可有多个after触发器。注意,不能在视图上定义after触发器。
for:与after相同,为兼容早期的SQL Server版本而设置。
instead of:指定执行触发器中的SQL语句而不执行触发SQL语句,从而代替触发语句的操作。在表或视图上,每个insert,update,delete语句最多可以定义一个instead of触发器。instead of触发器不能再使用了with check option选项的可更新视图上定义。
sql_statement:触发器被触发后要执行的SQL语句。

eg:创建一个触发器,当学生表中的记录被更新时,显示表中的所有记录。

create trigger student_change
   on student after insert,update,delete
   as
      select * from student;

eg:在Student表上创建delete触发器,实现Student表和SC表的级联删除。

create trigger studentDelete on Student
       after delete
as
       delete from SC
       where Son in(select deleted.Sno from deleted);

eg:在SC表上创建insert触发器,当向SC表中添加学生的选课记录时,检查该学生的Sno是否存在。若不存在,则不能将记录插入。

create trigger sc_insert on SC
   after insert
as
   if(select count(*) from Student,inserted
     where Student.Sno=inserted.Sno)=0
   begin
     print '学号不存在,不能插入该记录'
     rollback transaction
   end;
在该触发器中,当向SC表中添加记录后,首先检查Sno在Student表中是否存在,若不存在,则事务回滚。

eg:创建update触发器,禁止对Student表中学生的学号进行修改

create trigger student_update on Student
    after update
as
    if update(Sno)
    begin
       print '学生的学号不能修改'
       rollback transaction
    end;

eg:在SC表上创建触发器,当一次向SC表中添加多个记录时,删除学号在Student表中不存在的记录,从而保证数据的一致性。注意,不能在SC表中定义外键约束。

create trigger sc_insert on SC after insert
as
  if(select count(*)
    from Student,inserted
    where Student.Sno=inserted.Sno)<> @@rowcount
  begin
    delete from SC
    where Sno not in(select Sno from Student)
  end;
在该触发器被激活以前,insert操作已经把所有记录插入到SC表中了,这些记录可能包含学号在Student表中不存在的记录。当该触发器被激活后,判断插入到SC表的Sno是否都在Student表中存在。若有不存在的,则从SC表中删除那些Sno在Student表中不存在的记录。

eg:在视图上定义instead of触发器。

假设有一个反映学生出生年份的视图
create view birth_view(Sno,Sname,Ssex,Sbirth,Sdept)
as
  select Sno,Sname,Ssex,2008-Sage,Sdept
  from student;

在该视图中,学生的出生年份是通过计算得到的。若通过该视图向Student表中插入一条记录,例如(‘950021’,’李伟’,’男’,1987,’CS’),则可以在该视图上定义如下的instead of触发器来实现。

create trigger birth_view_insert on birth_view
instead of
as
    declare @Sno char(6)
    declare @Sname varchar(10)
    declare @Ssex char(2)
    declare @birth int
    declare @Sage int
    declare @Sdept char(20)
    select @Sno=Sno,@Sname=Sname,@Ssex=Ssex,@birth=Sbirth,@Sdept=Sdept
    from inserted
    set @Sage=2008-@birth
    insert into Student(Sno,Sname,Ssex,Sage,Sdept)
    values(@Sno,@Sname,@Ssex,@Sage,@Sdept);
   instead of触发器用于替代引起触发器执行的SQL语句。当向birth_view视图执行insert语句时,birth_view_insert触发器激活,此时inserted表中已经有了要插入的数据,如('950021','李伟','男',1987,'CS')。在birth_view_insert触发器代码中,计算@Sage=2008-@birth,然后将数据插入基本表Student中,而激发该触发器的insert语句不会被执行。
    例如,在birth_view视图执行插入语句
    insert into birth_view
    values('950021','李伟','男',1987,'CS');
    则可以将该记录插入到表Student中。

删除触发器

drop trigger trigger_name[,...n];

相关链接:http://www.cnblogs.com/rainman/p/3675834.html

  • 11
    点赞
  • 60
    收藏
    觉得还不错? 一键收藏
  • 5
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值