mysql 触发器详情

原文:https://www.cnblogs.com/duodushu/p/5446384.html

参考:https://www.yiibai.com/mysql/if-statement.html

          https://www.yiibai.com/mysql/triggers.html

实例:

创建触发器:before

DELIMITER $$
DROP TRIGGER IF EXISTS tg11;
CREATE TRIGGER `tg11` 
BEFORE INSERT ON `cy_pay_ok`
FOR EACH ROW 
begin
  declare point int; #申明变量
  declare agentPoint int;
  declare gameBasePoint int;
  declare gameMaxPoint int;
  set agentPoint=(SELECT point FROM cy_game_agent_point WHERE game_id=new.gameid AND agent=new.regagent);#变量赋值
  set gameBasePoint=(SELECT base_point FROM cy_game WHERE id=new.gameid);
  set gameMaxPoint=(SELECT max_point FROM cy_game WHERE id=new.gameid);

  /* if else 语句*/
  if(agentPoint) then
	   if(agentPoint<=gameMaxPoint) then 
        set point=agentPoint;
     elseif(agentPoint>gameMaxPoint) THEN
        set point=gameMaxPoint;
		 end if;
  elseif(gameBasePoint AND gameMaxPoint) then 
	   if(gameBasePoint<=gameMaxPoint) then 
        set point=gameBasePoint;
     elseif(gameBasePoint>gameMaxPoint) then
        set point=gameMaxPoint;
     end if;
  end if;
  SET new.agent_amount=new.amount*point/100;#在插入cy_pay_ok表前给字段赋值,该字段是cy_pay_ok字段
  SET new.point=point;
end$$
DELIMITER

查看触发器:

SHOW TRIGGERS from btmox where `table` like  '%cy_pay_ok%'  #btmox 数据库 

要执行SHOW TRIGGERS语句,您必须具有SUPER权限。

删除触发器:

DROP TRIGGER table_name.trigger_name;


after触发器

#触发器-游戏添加后生成游戏渠道点位
DELIMITER $$
DROP TRIGGER IF EXISTS after_cy_game_insert;
CREATE TRIGGER `after_cy_game_insert` 
AFTER INSERT ON `cy_game`
FOR EACH ROW 
begin
	INSERT INTO cy_game_agent_point(game_id,agent,point,created_user,created_at)
	SELECT
	new.id, agent,point,'sys',unix_timestamp(now())
	FROM
	cy_ct_cps_user 
	WHERE (agent IS NOT null && agent != '') and point !=0 AND point<=60;
end$$

SQL触发器是存储在数据库目录中的一组SQL语句。每当与表相关联的事件发生时,即会执行或触发SQL触发器,例如插入,更新或删除。

SQL触发器是一种特殊类型的存储过程。 这是特别的,因为它不像直接像存储过程那样调用。 触发器和存储过程之间的主要区别在于,当对表执行数据修改事件时,会自动调用触发器,而存储过程必须要明确地调用。

了解SQL触发器的优缺点非常重要,以便您可以适当地使用它。在以下部分中,我们将讨论使用SQL触发器的优缺点。

SQL触发器的优点

  • SQL触发器提供了检查数据完整性的替代方法。
  • SQL触发器可以捕获数据库层中业务逻辑中的错误。
  • SQL触发器提供了运行计划任务的另一种方法。通过使用SQL触发器,您不必等待运行计划的任务,因为在对表中的数据进行更改之前或之后自动调用触发器。
  • SQL触发器对于审核表中数据的更改非常有用。

SQL触发器的缺点

  • SQL触发器只能提供扩展验证,并且无法替换所有验证。一些简单的验证必须在应用层完成。 例如,您可以使用JavaScript或服务器端使用服务器端脚本语言(如JSPPHP,ASP.NET,Perl等)来验证客户端的用户输入。
  • 从客户端应用程序调用和执行SQL触发器不可见,因此很难弄清数据库层中发生的情况。
  • SQL触发器可能会增加数据库服务器的开销。

MySQL触发器简介

在MySQL中,触发器是一组SQL语句,当对相关联的表上的数据进行更改时,会自动调用该语句。 触发器可以被定义为在INSERTUPDATEDELETE语句更改数据之前或之后调用。在MySQL5.7.2版本之前,每个表最多可以定义六个触发器。

  • BEFORE INSERT - 在数据插入表之前被激活触发器。
  • AFTER INSERT - 在将数据插入表之后激活触发器。
  • BEFORE UPDATE - 在表中的数据更新之前激活触发器。
  • AFTER UPDATE - 在表中的数据更新之后激活触发器。
  • BEFORE DELETE - 在从表中删除数据之前激活触发器。
  • AFTER DELETE - 从表中删除数据之后激活触发器。

但是,从MySQL 5.7.2+版本开始,可以为相同的触发事件和动作时间定义多个触发器

当使用不使用INSERTDELETEUPDATE语句更改表中数据的语句时,不会调用与表关联的触发器。 例如,TRUNCATE语句删除表的所有数据,但不调用与该表相关联的触发器。

有些语句使用了后台的INSERT语句,如REPLACE语句LOAD DATA语句。如果使用这些语句,则调用与表关联的相应触发器。

必须要为与表相关联的每个触发器使用唯一的名称。可以为不同的表定义相同的触发器名称,这是一个很好的做法。

应该使用以下命名约定命名触发器:

(BEFORE | AFTER)_tableName_(INSERT| UPDATE | DELETE)
SQL

例如,before_order_update是更新orders表中的行数据之前调用的触发器。

以下命名约定与上述一样。

tablename_(BEFORE | AFTER)_(INSERT| UPDATE | DELETE)
SQL

例如,order_before_update与上述before_order_update触发器相同。

MySQL触发存储

MySQL在数据目录中存储触发器,例如:/data/yiibaidb/,并使用名为tablename.TRGtriggername.TRN的文件:

  • tablename.TRG文件将触发器映射到相应的表。
  • triggername.TRN文件包含触发器定义。

可以通过将触发器文件复制到备份文件夹来备份MySQL触发器。也可以使用mysqldump工具备份触发器

MySQL触发限制

MySQL触发器覆盖标准SQL中定义的所有功能。 但是,在应用程序中使用它们之前,您应该知道一些限制。

MySQL触发器不能:

  • 使用在SHOWLOAD DATALOAD TABLEBACKUP DATABASERESTOREFLUSHRETURN语句之上。
  • 使用隐式或明确提交或回滚的语句,如COMMITROLLBACKSTART TRANSACTIONLOCK/UNLOCK TABLESALTERCREATEDROPRENAME等。
  • 使用准备语句,如PREPAREEXECUTE
  • 使用动态SQL语句。


MySQL包含对触发器的支持。触发器是一种与表操作有关的数据库对象,当触发器所在表上出现指定事件时,将调用该对象,即表的操作事件触发表上的触发器的执行。

创建触发器
在MySQL中,创建触发器语法如下:

代码如下:


CREATE TRIGGER trigger_name
trigger_time
trigger_event ON tbl_name
FOR EACH ROW
trigger_stmt

其中:

trigger_name:标识触发器名称,用户自行指定;
trigger_time:标识触发时机,取值为 BEFORE 或 AFTER;
trigger_event:标识触发事件,取值为 INSERT、UPDATE 或 DELETE;
tbl_name:标识建立触发器的表名,即在哪张表上建立触发器;
trigger_stmt:触发器程序体,可以是一句SQL语句,或者用 BEGIN 和 END 包含的多条语句。

由此可见,可以建立6种触发器,即:BEFORE INSERT、BEFORE UPDATE、BEFORE DELETE、AFTER INSERT、AFTER UPDATE、AFTER DELETE。

另外有一个限制是不能同时在一个表上建立2个相同类型的触发器,因此在一个表上最多建立6个触发器。

trigger_event 详解
MySQL 除了对 INSERT、UPDATE、DELETE 基本操作进行定义外,还定义了 LOAD DATA 和 REPLACE 语句,这两种语句也能引起上述6中类型的触发器的触发。

LOAD DATA 语句用于将一个文件装入到一个数据表中,相当与一系列的 INSERT 操作。

REPLACE 语句一般来说和 INSERT 语句很像,只是在表中有 primary key 或 unique 索引时,如果插入的数据和原来 primary key 或 unique 索引一致时,会先删除原来的数据,然后增加一条新数据,也就是说,一条 REPLACE 语句有时候等价于一条。

INSERT 语句,有时候等价于一条 DELETE 语句加上一条 INSERT 语句。

INSERT 型触发器:插入某一行时激活触发器,可能通过 INSERT、LOAD DATA、REPLACE 语句触发;
UPDATE 型触发器:更改某一行时激活触发器,可能通过 UPDATE 语句触发;
DELETE 型触发器:删除某一行时激活触发器,可能通过 DELETE、REPLACE 语句触发。

BEGIN … END 详解
在MySQL中,BEGIN … END 语句的语法为:

BEGIN
[statement_list]
END
其中,statement_list 代表一个或多个语句的列表,列表内的每条语句都必须用分号(;)来结尾。
而在MySQL中,分号是语句结束的标识符,遇到分号表示该段语句已经结束,MySQL可以开始执行了。因此,解释器遇到statement_list 中的分号后就开始执行,然后会报出错误,因为没有找到和 BEGIN 匹配的 END。

这时就会用到 DELIMITER 命令(DELIMITER 是定界符,分隔符的意思),它是一条命令,不需要语句结束标识,语法为:
DELIMITER new_delemiter
new_delemiter 可以设为1个或多个长度的符号,默认的是分号(;),我们可以把它修改为其他符号,如$:
DELIMITER $
在这之后的语句,以分号结束,解释器不会有什么反应,只有遇到了$,才认为是语句结束。注意,使用完之后,我们还应该记得把它给修改回来。

一个完整的创建触发器示例
假设系统中有两个表:
班级表 class(班级号 classID, 班内学生数 stuCount)
学生表 student(学号 stuID, 所属班级号 classID)
要创建触发器来使班级表中的班内学生数随着学生的添加自动更新,代码如下:

代码如下:下载地址 springmvc+mybatis+spring 整合SSM   

DELIMITER $
create trigger tri_stuInsert after insert
on student for each row
begin
declare c int;
set c = (select stuCount from class where classID=new.classID);
update class set stuCount = c + 1 where classID = new.classID;
end$
DELIMITER ;

变量详解
MySQL 中使用 DECLARE 来定义一局部变量,该变量只能在 BEGIN … END 复合语句中使用,并且应该定义在复合语句的开头,

即其它语句之前,语法如下:

DECLARE var_name[,...] type [DEFAULT value]
其中:
var_name 为变量名称,同 SQL 语句一样,变量名不区分大小写;type 为 MySQL 支持的任何数据类型;
可以同时定义多个同类型的变量,用逗号隔开;变量初始值为 NULL,如果需要,可以使用 DEFAULT 子句提供默认值,值可以被指定为一个表达式。

对变量赋值采用 SET 语句,语法为:

SET var_name = expr [,var_name = expr] ...

NEW 与 OLD 详解

上述示例中使用了NEW关键字,和 MS SQL Server 中的 INSERTED 和 DELETED 类似,MySQL 中定义了 NEW 和 OLD,用来表示

触发器的所在表中,触发了触发器的那一行数据。
具体地:
在 INSERT 型触发器中,NEW 用来表示将要(BEFORE)或已经(AFTER)插入的新数据;
在 UPDATE 型触发器中,OLD 用来表示将要或已经被修改的原数据,NEW 用来表示将要或已经修改为的新数据;
在 DELETE 型触发器中,OLD 用来表示将要或已经被删除的原数据;
使用方法: NEW.columnName (columnName 为相应数据表某一列名)
另外,OLD 是只读的,
而 NEW 则可以在触发器中使用 SET 赋值,这样不会再次触发触发器,造成循环调用(如每插入一个学生前,都在其学号前加“2013”)。

查看触发器

和查看数据库(show databases;)查看表格(show tables;)一样,查看触发器的语法如下:

SHOW TRIGGERS [FROM schema_name];
其中,schema_name 即 Schema 的名称,在 MySQL 中 Schema 和 Database 是一样的,也就是说,可以指定数据库名,这样就

不必先“USE database_name;”了。

删除触发器

和删除数据库、删除表格一样,删除触发器的语法如下:

DROP TRIGGER [IF EXISTS] [schema_name.]trigger_name

触发器的执行顺序

我们建立的数据库一般都是 InnoDB 数据库,其上建立的表是事务性表,也就是事务安全的。这时,若SQL语句或触发器执行失败,MySQL 会回滚事务,有:

①如果 BEFORE 触发器执行失败,SQL 无法正确执行。
②SQL 执行失败时,AFTER 型触发器不会触发。
③AFTER 类型的触发器执行失败,SQL 会回滚


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值