数据库-触发器 trigger

说明:本文内容为网站上(博客园或CSDN)收集整理而来,是对相关知识的记录以方便及时复习学习,并非原创。 

 触发器每个数据库的创建方式不同,但作用都是类似的,触发器是一种特殊的存储过程,它不能被显式地调用,而是在往表中插入记录﹑更新记录或者删除记录时被自动地激活。

MySql 触发器

  1、概念

   触发器(trigger):监视某种情况,并触发某种操作。

   触发器的使用场景有:数据确认、实施复杂的安全性检查、做审计,跟踪表上所做的数据操作等、数据的备份和同步;  

   触发器也可以调用存储过程和存储函数。

   一个表相同的监听事件只能建一个触发器,比如插入操作引起的触发事件只能有一个,再建立因插入引起的触发会提示触发器创建失败。

   对于insert而言,新插入的行用new来表示,行中的每一列的值用new.列名来表示。

   对于delete而言:原本有一行,后来被删除,想引用被删除的这一行,用old来表示,old.列名可以引用被删除的行的值。

  2、语法

  触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/before) 4.触发事件(insert/update/delete)  

1 create trigger triggerName
2 after/before 
3 insert/update/delete on TableName
4 for each row   --这句话在mysql是固定的
5 begin
6     -- sql语句;
7 end;

  3、实例

   实例1:订单表t_order插入一条记录,更新商品表t_goods中对应的商品数量;   

1 DELIMITER //  --mysql的定义语句开始标志
2 create trigger trigger1
3 after insert on t_order 
4 for each row
5 begin 
6 update t_goods set num=num-new.much where id = new.id;
7 end //  --语句结束标志

    实例2:撤销一个订单的时,将对应商品的数量加回来;

1 DELIMITER//
2 create trigger trigger2
3 after delete on t_order
4 for each row
5 begin
6 update t_goods set num = num + old.much where id = old.g_id ;
7 end //

  实例3:修改一个订单的数量时,更新商品表的商品数量(where后面还可以写成:where id = new.g_id)

1 DELIMITER //
2 create trigger trigger3
3 after update on t_order
4 for each row
5 begin 
6 update t_goods set num=num+old.much-new.much where id = old.g_id ; 
7 end //

   实例4:插入订单表时同时插入订单日志表,记录订单日志,且日志表需要用到订单表的主键(插入一张表时需要用到另一张表的主键);

1 DELIMITER//
2 create trigger trigger4
3 after insert on t_order 
4 for each row
5 begin
6 insert into t_order_log (o_id,createtime) values(new.id,now());
7 end//


SQL Server 触发器

  1、概念

    与MySQL不同的是,触发器的触发时机不实用"after/before"而是用"instead of/after";

    一个表或视图的每一个修改动作(Insert、Update和Delete)都可以有一个“Instead of” 触发器,一个表的每个修改动作都可以有多个“After”触发器。

  2、两张内存中的逻辑表Inserted和Deleted

    SQL Server为每个触发器都创建了两个专用表:Inserted表和Deleted表。    

    • 这两个表由系统来维护,它们存在于内存中而不是在数据库中,可以理解为一个虚拟的表。
    • 这两个表的结构总是与被该触发器作用的表的结构相同。
    • 触发器执行完成后,与该触发器相关的这两个表也被删除。
    • Deleted表存放由于执行Delete或Update语句而要从表中删除的所有行。
    • Inserted表存放由于执行Insert或Update语句而要向表中插入的所有行。
              操作    Inserted逻辑表    Deleted逻辑表
增加记录(insert) 存放增加的记录  
删除记录(delete)   存放被删除的记录
修改记录(update) 存放更新后的记录 存放更新前的记录

  3、语法    

 1 --创建触发器
 2 create trigger triggerName 
 3 on  {table_name|view_name} 
 4 {After|Instead of} 
 5 {insert|update|delete}
 6 as 
 7 begin
 8      --逻辑处理语句
 9 end
10 
11 --查看所有触发器
12 select * from sysobjects where xtype='TR'

  4、实例

  实例1:

  实现功能:在删除学生表(students)时,如果借书表(borrowRecord)中仍有记录(未还)则不能删除;  

1 Create trigger trig_students_delete
2 on students
3 instead of delete
4 as
5 begin
6     if not exists(select * from borrowRecord b,deleted d where b.studentId = d.id)
7         delete students where id in (select id from deleted )        
8 end

  说明:line6中用到了deleted这个虚拟表,因为该触发器创建在表students上,所以这里的deleted表结构和students一模一样;当students有删除操作时,会将students中删除的记录写到表deleted中,所以line6中的select语句查询的正是:查询被删除学生是否在借书表borrowRecord中还有记录;

  注意:当被删学生(id=2)还有借阅记录时,执行delete students where id = 2;删除操作时,语句执行正常,但是实际上该学生记录并没有在students表中删掉。这种情况容易导致bug,所以检查是否还有借阅记录可以先查出来放到程序里判断;

  实例2: 在订单表(OrderRecord)建立一个插入触发器,在添加一条订单时,减少商品表(prodect)相应的货品记录中的库存。  

1 create trigger trigger_OrderRecord_insert
2 on OrderRecord
3 after insert
4 as
5 begin
6     update prodect set number = number - inserted.num
7     from prodect , inserted 
8     where prodect.pid = inserted.pid
9 end

  说明:line6中用到了inserted这个虚拟表,因为该触发器创建在表OrderRecord上,所以这里的inserted表结构和OrderRecord一模一样;当OrderRecord有插入操作时,会将OrderRecord中插入的记录写到表inserted中;

附注:

  以上内容参考来自博客园园友的宝贵资料汇总整理,详细:http://www.cnblogs.com/rainman/p/3675834.html、http://www.cnblogs.com/zzwlovegfj/archive/2012/07/04/2576989.html

原文地址:https://www.cnblogs.com/crazytrip/p/5977875.html