触发器

    MySQL语句在需要时被执行,存储过程也是如此。但是,如果你想要某条语句(或某些语句)在事件发生时自动执行,怎么办呢?例如:每当增加一个顾客到某个数据库表时,都检查其电话号码格式是否正确,州的缩写是否为大写;每当订购一个产品时,都从库存数量中减去订购的数量;无论何时删除一行,都在某个存档表中保留一个副本。
    所有这些例子的共同之处是它们都需要在某个表发生更改时自动处理某个动作。这确切地说就是一个触发器。 触发器是MySQL 响应以下任意语句而自动执行任意其他的一条 MySQL语句(或位于BEGIN和 END语句之间的一组语句)
        1、DELECT
        2、INSERT
        3、UPDATE
其他的mysql语句不支持触发器的。
 
创建触发器
    在创建触发器时,需要给出 4条信息:
        1、唯一的触发器名;
        2、触发器关联的表
        3、触发器应该响应的动作( DELETE、INSERT 或UPDATE)
        4、触发器何时执行(处理之前或之后)。
    注意:保持每个数据库的触发器名唯一。
    触发器用 CREATE TRIGGER语句创建。下面是一个简单的例子:
mysql> DELIMITER //
mysql> CREATE TRIGGER newproduct AFTER INSERT ON products
-> FOR EACH ROW
-> SELECT 'added ' INTO @ee;
-> //
Query OK, 0 rows affected (0.05 sec)
    CREATE TRIGGER用来创建名为newproduct的新触发器。触发器可在一个操作发生之前或之后执行,这里给出了 AFTER INSERT,所以此触发器将在 INSERT语句成功执行后执行。FOR EACH ROW是触发器的执行间隔,FOR EACH ROW子句通知触发器每隔一行执行一次动作,而不是对整个表执行一次。在这个例子中,文本 added将对每个插入的行显示一次。为了测试这个触发器,使用 INSERT语句添加一行或多行到products中,你将看到对每个成功的插入。
mysql> insert into products (prod_id, vend_id, prod_name, prod_price, prod_desc)
-> values
-> ('TNT3', 1002, 'liwei', 123.12, 'dudu jiushi ni')
-> //
Query OK, 1 row affected (0.03 sec)
    在使用select来查询变量ee,看看结果是什么
select @ee
//
    结果是:
+------+
| @ee |
+------+
| added |
+------+
    注意:只有表才支持触发器,视图不支持(临时表也不支持)。
    触发器按每个表每个事件每次地定义,每个表每个事件每次只允许一个触发器。因此,每个表最多支持 6个触发器(每条INSERT、 UPDATE和DELETE的之前和之后)。单一触发器不能与多个事件或多个表关联,所以,如果你需要一个对 INSERT和UPDATE 操作执行的触发器,则应该定义两个触发器。
    注意:如果BEFORE触发器失败,则 MySQL将不执行请求的操作。此外,如果 BEFORE触发器或语句本身失败, MySQL将不执行 AFTER触发器(如果有的话)。
 
删除触发器
    现在,删除触发器的语法应该很明显了。为了删除一个触发器,可使用 DROP TRIGGER语句,如下所示:
DROP TRIGGER newproduct  
    触发器不能更新或覆盖。为了修改一个触发器,必须先删除它,然后再重新创建。
 
使用触发器
    在有了前面的基础知识后,我们现在来看所支持的每种触发器类型以及它们的差别。
 
INSERT触发器
    INSERT触发器在INSERT 语句执行之前或之后执行。需要知道以下几点:
        1、在INSERT触发器代码内,可引用一个名为 NEW的虚拟表,访问被插入的行。
        2、在BEFORE INSERT触发器中, NEW中的值也可以被更新(允许更改被插入的值);
        3、对于 AUTO_INCREMENT列,NEW 在INSERT执行之前包含 0,在INSERT执行之后包含新的自动生成值。
    下面举一个例子(一个实际有用的例子)。 AUTO_INCREMENT列具有MySQL自动赋予的值。第21章建议了几种确定新生成值的方法,但下面是一种更好的方法:
mysql> create trigger neworder after insert on orders
-> for each row select new.order_num into @liwei;
    此代码创建一个名为 neworder的触发器,它按照AFTER INSERTON orders执行。在插入一个新订单到 orders表时,MySQL 生成一个新订单号并保存到 order_num中。触发器利用select 语句的返回结果,从NEW. order_num取得这个值并赋值给变量liwei。此触发器必须按照 AFTER INSERT执行,因为在BEFORE INSERT语句执行之前,新order_num还没有生成。对于 orders的每次插入使用这个触发器将总是返回新的订单号。接着我们插入新的数据看看。
mysql> insert into orders(order_date,cust_id)
-> values (Now(), 10001);
    数据插入完成之后,我们来使用liwei变量来查询新的订单号。
mysql> select @liwei;
    结果:
+--------+
| @liwei |
+--------+
| 20010 |
+--------+
1 row in set (0.02 sec)
    orders 表包含3 个列。order_date 和 cust_id 必须给出,order_num由MySQL 自动生成,而现在 order_num 输出赋值给一个变量。然后利用这个变量做返回。
通常,将 BEFORE 用于数据验证和净化(目的是保证插入表中的数据确实是需要的数据)。本提示也适用于 UPDATE触发器。
 
DELETE触发器
    DELETE 触发器在DELETE 语句执行之前或之后执行。需要知道以下两点:
        1、在 DELETE触发器代码内,你可以引用一个名为 OLD 的虚拟表,访问被删除的行;
        2、OLD 中的值全都是只读的,不能更新。
    下面的例子演示使用 OLD 保存将要被删除的行到一个存档表中:
mysql> create trigger deleteorder before delete on orders
-> for each row select old.order_num,old.order_date into @liwei,@tx;
    删除一条数据:
mysql> delete from orders where order_num = 10002;
Query OK, 1 row affected (0.14 sec)
    我们来看看查询上面声明的两个变量(liwei与tx)
mysql> select @liwei;
    输出:
+--------+
| @liwei |
+--------+
| 10002 |
+--------+
    或者是如下语句一条数据。
create trigger deleteorder before delete on orders
for each row
begin
insert into otherorder (order_num, prder, cust_id)
values
( old.order_num, old.order_date, old.cust_id);
    在任意订单被删除前将执行此触发器。它使用一条 INSERT 语句将 OLD中的值(要被删除的订单)保存到一个名为 otherorder的存档表中(为实际使用这个例子,你需要用与 orders 相同的列创建一个名为 otherorder的表)。
    使用 BEFORE DELETE 触发器的优点(相对于 AFTER DELETE触发器来说)为,如果由于某种原因,订单不能存档, DELETE 本身将被放弃。
    正如所见,触发器 deleteorder 使用BEGIN 和END 语句标记触发器体。这在此例子中并不是必需的,不过也没有害处。使用 BEGIN END 块的好处是触发器能容纳多条 SQL语句(在 BEGIN END 块中一条挨着一条)。
 
UPDATE触发器
    UPDATE 触发器在UPDATE 语句执行之前或之后执行。需要知道以下几点:
        1、在 UPDATE触发器代码中,你可以引用一个名为 OLD 的虚拟表访问以前( UPDATE 语句前)的值,引用一个名为 NEW 的虚拟表访问新更新的值;
        2、在 BEFORE UPDATE触发器中, NEW 中的值可能也被更新(允许更改将要用于 UPDATE 语句中的值);
        3、OLD 中的值全都是只读的,不能更新。
    下面的例子保证州名缩写总是大写(不管 UPDATE 语句中给出的是大写还是小写):
mysql> create trigger upvendor before update on vendors
-> for each row set new.vend_state = upper(new.vend_state);
Query OK, 0 rows affected (0.21 sec)
    显然任何数据净化都需要在update语句之前进行。就像这个例子中的一样。每次在更新一行时, NEW.vend_state中的值(将用来更新表行的值)都用 Upper(NEW.vend_state) 替换。
 
关于触发器的进一步介绍
    1、创建触发器可能需要特殊的安全访问权限,但是,触发器的执行是自动的。如果 INSERT 、UPDATE 或 DELETE语句能够执行,则相关的触发器也能执行。
    2、应该用触发器来保证数据的一致性(大小写、格式等)。在触发器中执行这种类型的处理的优点是它总是进行这种处理,而且是透明地进行,与客户机应用无关。
    3、触发器的一种非常有意义的使用是创建审计跟踪。使用触发器,把更改(如果需要,甚至还有之前和之后的状态)记录到另一个表非常容易。
    4、遗憾的是, MySQL 触发器中不支持 CALL语句。这表示不能从触发器内调用存储过程。所需的存储过程代码需要复制到触发器内。
 
    关于什么时候使用new,old这两个关键字就好像字面意思新旧一样:
         INSERT 只有NEW
        
UPDATE既有NEW又和OLD
        
DELETE只有OLD 
    所以对于INSERT语句,只有NEW是合法的;对于DELETE语句,只有OLD才合法;而UPDATE语句可以在和NEW以及 OLD同时使用。下面是一个UPDATE中同时使用NEW和OLD的例子。

CREATE TRIGGER tr1
BEFORE UPDATE ON liwei
FOR EACH ROW
BEGIN
SET @old = OLD.s1;
SET @new = NEW.s1;
END;
    现在如果liwei表中的s1列的值是55,也就是@new的值就是55,那么执行了"UPDATE liwei SET s1 = s1 + 1"之后@old的值会变成55,
 
    另外按照我在使用trigger和function的时候在mysql的trigger和function中不能出现select * from table形式的查询,因为其会返回一个结果集;而这在mysql的trigger和function中是不可接受的,但是在存储过程中可以。在 trigger和function中可以使用select ... into ...形式的查询。比如在使用trigger的时候没有into 的时候会报这样一种错误:

not allowed to return a result set from a trigger

mysql之触发器的更多相关文章

  1. mysql之触发器trigger 详解

    为了梦想,努力奋斗! 追求卓越,成功就会在不经意间追上你 mysql之触发器trigger 触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table)  ...

  2. 初试mysql存储过程&触发器

    玩mysql以来,一直没有试过实现存储过程,因为存储过程的语法看起来有些笨重.所以一直采用手动批量运行查询,而且要手动改日期之类的参数. 今天尝试着学了一会,发现其实是很简单的.语法上确实格式复杂些, ...

  3. MySql之触发器的使用

    一:触发器的使用场景 当数据库的记录发生变化时,自动触发某些操作. MySQL的触发器响应三种操作,六种场合: 三种操作:DELETE.INSERT.UPDATE. 六种场合:三种操作的BEFORE. ...

  4. MYSQL:基础——触发器

    MYSQL基础——触发器 引入触发器 什么是触发器 如果你想要某条语句(或某些语句)在事件发生时自动执行.比如: 每当订购一个产品时,都从库存数量中减去订购的数量:无论何时删除一行,都在某个存档表中保 ...

  5. MySQL创建触发器的时候报1419错误( 1419 - You do not have the SUPER privilege and binary logging is enabled )

    mysql创建触发器的时候报错: 解决方法:第一步,用root用户登录:mysql -u root -p第二步,设置参数log_bin_trust_function_creators为1:set gl ...

  6. mysql 视图 触发器 存储过程 函数事务 索引

    mysql 视图 触发器 存储过程 函数事务 索引 视图 视图是一个虚拟表(非真实存在),其本质是[根据SQL语句获取动态的数据集,并为其命名],用户使用时只需使用[名称]即可获取结果集,并可以将其当 ...

  7. mysql之触发器trigger

    触发器(trigger):监视某种情况,并触发某种操作. 触发器创建语法四要素:1.监视地点(table) 2.监视事件(insert/update/delete) 3.触发时间(after/befo ...

  8. mysql优化--触发器和auto_increment

    1.触发器: 触发器的好处:做数据回收站或者做数据关联删除 触发器的坏处:给数据库增加压力,增删改变慢,不利与mysql移到其他数据库会出问题. 触发器建立:只能增删改,查不能建立. 例子1:创建一个 ...

  9. mysql之触发器入门

    触发器语法: CREATE TRIGGER <触发器名称>  --触发器必须有名字,最多64个字符,可能后面会附有分隔符.它和MySQL中其他对象的命名方式基本相象.{ BEFORE |  ...

  10. MySql之触发器【过度变量 new old】

    trigger是由事件触发某个操作.这些事件包括insert语句.update语句和delete语句.当数据库执行这些事件时,就会激活触发器执行相应的操作. [1]只有一个执行语句 create tr ...

随机推荐

  1. Android UI 组件 » GifView

    GifView 是一个为了解决android中现在没有直接显示gif的view,只能通过mediaplay来显示这个问题的项目,其用法和 ImageView一样,支持gif图片 使用方法: 1-把Gi ...

  2. .net 的生成操作

    生成操作(BuildAction) 属性:BuildAction 属性指示 Visual Studio .NET 在执行生成时对文件执行的操作. BuildAction 可以具有以下几个值之一: 无( ...

  3. IOS应用程序升级

    IOS应用程序升级流程介绍:IOS手机端应用程序需要升级时,打开服务器端html文件(本文为ucab.html文件)->点击在线安装->打开plist文件(本文中为ucab.plist文件 ...

  4. datawindow直接导入导出xml

    long dwcontrol.ImportFile ( XML!, filename ) dw_.Modify("DataWindow.Export.XML.UseTemplate = 't ...

  5. [shell基础]——read命令

    read命令:在shell中主要用于读取输入.变量.文本 1. 接受标准输入(键盘)的输入,并将输入的数据赋值给设置的变量      [按回车键——表示输入完毕]      [若输入的数据多于设置的变 ...

  6. 20145120 《Java程序设计》实验二实验报告

    20145120 <Java程序设计>实验二实验报告 实验名称:Java面向对象程序设计 实验目的与要求: 初步掌握单元测试和TDD 理解并掌握面向对象三要素:封装.继承.多态 初步掌握U ...

  7. (转)c语言学习volatile

    原文网址:http://www.cnblogs.com/chio/archive/2007/11/24/970632.html 参考网址:http://www.embedu.org/Column/Co ...

  8. jQuery 效果 - slideDown() 方法[菜单导航栏常用]

    实例 以滑动方式显示隐藏的 <p> 元素: $(".btn2").click(function(){ $("p").slideDown(); }); ...

  9. HDU 3555 Bomb 数位dp

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3555 Bomb Time Limit: 2000/1000 MS (Java/Others) Mem ...

  10. JavaScript对象进阶

    要了解JavaScript对象,我们可以从对象创建.属性操作.对象方法这几个方面入手.概括起来,包括以下几模块: 1.创建对象 1.1 对象直接量 对象直接量是创建对象最简单的方式,由若干名/值对组成 ...