zoukankan      html  css  js  c++  java
  • mysql触发器

    mysql手册

    一、触发器

    1、触发器(trigger)是一种与表操作有关的数据库对象,该对象与编程语言中的函数非常类似,需要先声明后执行,并由事件来触发执行。

    2、触发器结构组成

    CREATE TRIGGER trigger_name #触发器名
    trigger_time #触发时机,取值为 BEFORE 或 AFTER
    trigger_event #触发事件,取值为 INSERT、UPDATE 或 DELETE
    ON tbl_name #建立触发器的表名,即在哪张表上建立触发器 FOR EACH ROW trigger_stmt #触发器程序体,可以是一句SQL语句,或者用 BEGIN 和 END 包含的多条语句

      注意:1)trigger_event中的INSERT包括INSERT、LOAD DATA(用户高速的向数据库中做批量mysql导入数据load data infile用法)和REPLACE(向表中插入多条记录,如:replace into table (id,name) values('1','aa'),('2','bb'))语句,DELETE包括DELETE和REPLACE语句

         2)对于某一表,不能有两个BEFORE UPDATE触发程序。但可以有1个BEFORE UPDATE触发程序和1个BEFORE INSERT触发程序,或1个BEFORE UPDATE触发程序和1个AFTER UPDATE触发程序

         3)tbl_name必须引用永久性表。不能将触发程序与TEMPORARY表(临时表)或视图关联起来

         4)触发程序(trigger_stmt中)不能调用将数据返回客户端的存储程序(如SELECT查询),也不能使用采用CALL语句的动态SQL(允许存储程序通过参数将数据返回触发程序)。触发程序也不能使用以显式或隐式方式开始或结束事务的语句,如START TRANSACTION、COMMIT或ROLLBACK。

    3、作用

      请参考mysql触发器的作用及语法

    二、触发器操作

    测试用表

    CREATE TABLE `t_dept` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `dname` varchar(20) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1
    CREATE TABLE `t_diary` (
      `id` bigint(20) NOT NULL AUTO_INCREMENT,
      `createtime` datetime NOT NULL,
      `dept` varchar(20) NOT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=34 DEFAULT CHARSET=latin1

    1、创建

    CREATE TRIGGER tri_dept#触发器名 
    BEFORE INSERT #触发时间(有BEFORE、AFTER)、事件(有INSERT、DELETE、UPDATE)
    ON t_dept FOR EACH ROW #触发器作用的表
    BEGIN #激活触发器后执行的语句,可以是多条,以";"分开
    INSERT INTO t_diary VALUES (NULL, NOW(), new.dname); #new.dname为触发事件的列
    END

      触发器实现在向t_dept表中插入数据前先向t_diary中插入一条数据

    CREATE TRIGGER tri_dept_add
    AFTER INSERT 
    ON t_dept FOR EACH ROW
    BEGIN
    UPDATE t_diary SET dept = concat(dept ,new.dname) WHERE id = 32;
    END

      注意:使用OLD和NEW关键字,能够访问受触发程序影响的行中的列(OLD和NEW不区分大小写)。在INSERT触发程序中,仅能使用NEW.col_name,没有旧行。在DELETE触发程序中,仅能使用OLD.col_name,没有新行。在UPDATE触发程序中,可以使用OLD.col_name来引用更新前的某一行的列,也能使用NEW.col_name来引用更新后的行中的列。

      用OLD命名的列是只读的。你可以引用它,但不能更改它。对于用NEW命名的列,如果具有SELECT权限,可引用它。在BEFORE触发程序中,如果你具有UPDATE权限,可使用“SET NEW.col_name = value”更改它的值。这意味着,你可以使用触发程序来更改将要插入到新行中的值,或用于更新行的值。

      在BEFORE触发程序中,AUTO_INCREMENT列的NEW值为0,不是实际插入新记录时将自动生成的序列号。

      另外:在mysql有些版本使用上述语句在begin end地方报错,无法执行,可以使用“分隔符”解决,代码如下

    DELIMITER |
    CREATE TRIGGER tri_dept_add
    AFTER INSERT 
    ON t_dept FOR EACH ROW
    BEGIN
    UPDATE t_diary SET dept = concat(dept ,new.dname) WHERE id = 32;
    END
    | DELIMITER ;

    2、查看

      SHOW TRIGGERS;

    3、删除

      DROP TRIGGER 触发器名; #如DROP TRIGGER tri_dept_add;

    4、事务

      触发器本身不支持事务操作,文档原话“触发程序不能使用以显式或隐式方式开始或结束事务的语句,如START TRANSACTION、COMMIT或ROLLBACK”,另外又有“对于事务性表,如果触发程序失败(以及由此导致的整个语句的失败),该语句所执行的所有更改将回滚。对于非事务性表,不能执行这类回滚,因而,即使语句失败,失败之前所作的任何更改依然有效”,即触发器是否有事务取决于原生语句。

      创建如下触发器,当触发器语句报错后将回滚所有执行语句

    CREATE TRIGGER tri_dept_add
    AFTER INSERT 
    ON t_dept FOR EACH ROW
    BEGIN
        insert t_diary SET id = 1,dept = new.dname;
    END;

    5、最后

      在BEGIN块中,还能使用存储子程序中允许的其他语法,如条件和循环等

    DROP TRIGGER IF EXISTS upd_check;
    DELIMITER |
    CREATE TRIGGER upd_check BEFORE UPDATE ON account
    FOR EACH ROW
    BEGIN
        IF NEW.amount < 0 THEN
             SET NEW.amount = 0;
         ELSEIF NEW.amount > 100 THEN
             SET NEW.amount = 100;
         END IF;
    END;
    | DELIMITER;
  • 相关阅读:
    poj 3321 Apple Tree
    hdu 1520 Anniversary party
    Light OJ 1089 Points in Segments (II)
    Timus 1018 Binary Apple Tree
    zoj 3299 Fall the Brick
    HFUT 1287 法默尔的农场
    Codeforces 159C String Manipulation 1.0
    GraphQL + React Apollo + React Hook 大型项目实战(32 个视频)
    使用 TypeScript & mocha & chai 写测试代码实战(17 个视频)
    GraphQL + React Apollo + React Hook + Express + Mongodb 大型前后端分离项目实战之后端(19 个视频)
  • 原文地址:https://www.cnblogs.com/sunjf/p/mysql_trigger.html
Copyright © 2011-2022 走看看