详解mysql触发器trigger实例

作者:周伯通的麦田 时间:2024-01-20 22:28:29 

MySQL好像从5.0.2版本就开始支持触发器的功能了,本次博客就来介绍一下触发器,首先还是谈下概念性的东西吧:

什么是触发器

触发器是与表有关的数据库对象,在满足定义条件时触发,并执行触发器中定义的语句集合。触发器的这种特性可以协助应用在数据库端确保数据的完整性。

举个例子,比如你现在有两个表【用户表】和【日志表】,当一个用户被创建的时候,就需要在日志表中插入创建的log日志,如果在不使用触发器的情况下,你需要编写程序语言逻辑才能实现,但是如果你定义了一个触发器,触发器的作用就是当你在用户表中插入一条数据的之后帮你在日志表中插入一条日志信息。当然触发器并不是只能进行插入操作,还能执行修改,删除。

创建触发器

创建触发器的语法如下:


CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmt
trigger_name:触发器的名称
tirgger_time:触发时机,为BEFORE或者AFTER
trigger_event:触发事件,为INSERT、DELETE或者UPDATE
tb_name:表示建立触发器的表明,就是在哪张表上建立触发器
trigger_stmt:触发器的程序体,可以是一条SQL语句或者是用BEGIN和END包含的多条语句
所以可以说MySQL创建以下六种触发器:
BEFORE INSERT,BEFORE DELETE,BEFORE UPDATE
AFTER INSERT,AFTER DELETE,AFTER UPDATE

其中,触发器名参数指要创建的触发器的名字

BEFOREAFTER参数指定了触发执行的时间,在事件之前或是之后

FOR EACH ROW表示任何一条记录上的操作满足触发事件都会触发该触发器

创建有多个执行语句的触发器


CREATE TRIGGER 触发器名 BEFORE|AFTER 触发事件
ON 表名 FOR EACH ROW
BEGIN
   执行语句列表
END

其中,BEGIN与END之间的执行语句列表参数表示需要执行的多个语句,不同语句用分号隔开

tips:

一般情况下,mysql默认是以 ; 作为结束执行语句,与触发器中需要的分行起冲突

为解决此问题可用DELIMITER,如:DELIMITER ||,可以将结束符号变成||

当触发器创建完成后,可以用DELIMITER ;来将结束符号变成;


mysql> DELIMITER ||
mysql> CREATE TRIGGER demo BEFORE DELETE
   -> ON users FOR EACH ROW
   -> BEGIN
   -> INSERT INTO logs VALUES(NOW());
   -> INSERT INTO logs VALUES(NOW());
   -> END
   -> ||
Query OK, 0 rows affected (0.06 sec)

mysql> DELIMITER ;

上面的语句中,开头将结束符号定义为||,中间定义一个触发器,一旦有满足条件的删除操作

就会执行BEGIN和END中的语句,接着使用||结束

最后使用DELIMITER ; 将结束符号还原

tigger_event:

详解mysql触发器trigger实例

load data语句是将文件的内容插入到表中,相当于是insert语句,而replace语句在一般的情况下和insert差不多,但是如果表中存在primary 或者unique索引的时候,如果插入的数据和原来的primary key或者unique相同的时候,会删除原来的数据,然后增加一条新的数据,所以有的时候执行一条replace语句相当于执行了一条delete和insert语句。

触发器可以是一条SQL语句,也可以是多条SQL代码块,那如何创建呢?


DELIMITER $  #将语句的分隔符改为$
BEGIN
sql1;
sql2;
...
sqln
END $
DELIMITER ;  #将语句的分隔符改回原来的分号";"

在BEGIN...END语句中也可以定义变量,但是只能在BEGIN...END内部使用:


DECLARE var_name var_type [DEFAULT value] #定义变量,可指定默认值
SET var_name = value  #给变量赋值

NEW和OLD的使用:

详解mysql触发器trigger实例

根据以上的表格,可以使用一下格式来使用相应的数据:


NEW.columnname:新增行的某列数据
OLD.columnname:删除行的某列数据

说了这么多现在我们来创建一个触发器吧!

现在有表如下:

用户users表


CREATE TABLE `users` (
 `id` int(11) unsigned NOT NULL AUTO_INCREMENT,
 `name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL,
 `add_time` int(11) DEFAULT NULL,
 PRIMARY KEY (`id`),
 KEY `name` (`name`(250)) USING BTREE
) ENGINE=MyISAM AUTO_INCREMENT=1000001 DEFAULT CHARSET=latin1;

日志logs表:


CREATE TABLE `logs` (
 `Id` int(11) NOT NULL AUTO_INCREMENT,
 `log` varchar(255) DEFAULT NULL COMMENT '日志说明',
 PRIMARY KEY (`Id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='日志表';

需求是:当在users中插入一条数据,就会在logs中生成一条日志信息。

创建触发器:


DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;#后面发现中文字符编码出现乱码,这里设置字符集
SET s2 = " is created";
SET s1 = CONCAT(NEW.name,s2);     #函数CONCAT可以将字符串连接
INSERT INTO logs(log) values(s1);
END $
DELIMITER ;

这里我用的navicat:

详解mysql触发器trigger实例

查看触发器

SHOW TRIGGERS语句查看触发器信息

详解mysql触发器trigger实例

Tip:


上面我用的navicat直接创建,如果大家用的mysql front,name这里会有个区别,我们删除刚才的触发器,在Mysql front中测试

drop trigger  user_log;#删除触发器

打开Mysql Front:

详解mysql触发器trigger实例

mysql front在编译sql时,不用定义结尾分隔符,修改后的sql直接这样既可:


#DELIMITER $
CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROW
BEGIN
DECLARE s1 VARCHAR(40)character set utf8;
DECLARE s2 VARCHAR(20) character set utf8;
SET s2 = " is created";
SET s1 = CONCAT(NEW.name,s2);     #函数CONCAT可以将字符串连接
INSERT INTO logs(log) values(s1);
END #$
#DELIMITER ;

详解mysql触发器trigger实例

这里再啰嗦几句:

tipsSHOW TRIGGERS语句无法查询指定的触发器

在triggers表中查看触发器信息


SELECT * FROM information_schema.triggers;

详解mysql触发器trigger实例

结果显示了所有触发器的详细信息,同时,该方法可以查询制定触发器的详细信息


SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME='user_log';

tips:

所有触发器信息都存储在information_schema数据库下的triggers表中

可以使用SELECT语句查询,如果触发器信息过多,最好通过TRIGGER_NAME字段指定查询

回到上面,我们创建好了触发器,继续在users中插入数据并查看数据:


insert into users(name,add_time) values('周伯通',now());

好吧,我们再来查看一下logs表吧!

详解mysql触发器trigger实例

通过上面的例子,可以看到只需要在users中插入用户的信息,日志会自动记录到logs表中,这也许就是触发器给我带来的便捷吧!

限制和注意事项

触发器会有以下两种限制:

1.触发程序不能调用将数据返回客户端的存储程序,也不能使用采用CALL语句的动态SQL语句,但是允许存储程序通过参数将数据返回触发程序,也就是存储过程或者函数通过OUT或者INOUT类型的参数将数据返回触发器是可以的,但是不能调用直接返回数据的过程。

2.不能再触发器中使用以显示或隐式方式开始或结束事务的语句,如START TRANS-ACTION,COMMIT或ROLLBACK。

注意事项:MySQL的触发器是按照BEFORE触发器、行操作、AFTER触发器的顺序执行的,其中任何一步发生错误都不会继续执行剩下的操作,如果对事务表进行的操作,如果出现错误,那么将会被回滚,如果是对非事务表进行操作,那么就无法回滚了,数据可能会出错。

来源:https://www.cnblogs.com/phpper/p/7587031.html

标签:mysql,触发器,trigger,实例
0
投稿

猜你喜欢

  • 编写一个JS组件来说说call和apply的用法

    2008-11-23 17:11:00
  • matplotlib grid()设置网格线外观的实现

    2021-08-26 08:39:13
  • python实现字符串和日期相互转换的方法

    2022-09-02 04:05:55
  • 如何使用pyinstaller打包多个和单个python文件详解

    2023-03-30 10:48:26
  • 科学知识:理解socket

    2022-11-28 09:50:07
  • Python入门之字符串操作详解

    2023-01-27 18:45:08
  • alt键 chr码值对应列表查看方法

    2022-02-21 06:41:33
  • 浅谈pytorch池化maxpool2D注意事项

    2023-07-14 15:02:30
  • Oracle中sql语句如何执行日志查询

    2024-01-23 21:43:26
  • 常用于后台开发的jQuery插件

    2010-09-25 12:47:00
  • PyQt5实现简单的计算器

    2022-09-27 07:44:39
  • CentOS 7.0如何启动多个MySQL实例教程(mysql-5.7.21)

    2024-01-14 10:56:45
  • 编写SQL需要注意的细节Checklist总结

    2012-10-07 10:43:57
  • 何处安放的Loading

    2011-08-10 19:11:20
  • PyQt5每天必学之关闭窗口

    2022-07-29 21:41:32
  • 巧制可全屏拖动的图片

    2008-05-09 19:34:00
  • 低版本中Python除法运算小技巧

    2021-11-14 00:54:00
  • 细品Dreamweaver MX 2004内建FW技术

    2010-09-02 12:38:00
  • php基于curl实现随机ip地址抓取内容的方法

    2023-11-14 22:29:45
  • 用户如何有效地利用ORACLE数据字典

    2008-03-04 18:19:00
  • asp之家 网络编程 m.aspxhome.com