目录
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
复制代码
此中,触发器名参数指要创建的触发器的名字复制代码 和复制代码 参数指定了触发实行的时间,在变乱之前或是之后复制代码 表现任何一条记录上的利用满足触发变乱都会触发该触发器
创建有多个实行语句的触发器- 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 ; 将竣事符号还原复制代码
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的利用:
根据以上的表格,可以利用一下格式来利用相应的数据:- 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:
检察触发器
SHOW TRIGGERS语句检察触发器信息
Tip:- 上面我用的navicat直接创建,如果大家用的mysql front,name这里会有个区别,我们删除刚才的触发器,在Mysql front中测试
复制代码
- drop trigger user_log;#删除触发器
复制代码
打开Mysql Front:
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 ;
复制代码
这里再啰嗦几句:
tips:复制代码 语句无法查询指定的触发器
在triggers表中检察触发器信息- SELECT * FROM information_schema.triggers;
复制代码
结果显示了所有触发器的详细信息,同时,该方法可以查询制定触发器的详细信息- 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表吧!
通过上面的例子,可以看到只必要在users中插入用户的信息,日记会主动记录到logs表中,这大概就是触发器给我带来的便捷吧!
限制和留意事项
触发器会有以下两种限制:
1.触发步伐不能调用将数据返回客户端的存储步伐,也不能利用接纳CALL语句的动态SQL语句,但是答应存储步伐通过参数将数据返回触发步伐,也就是存储过程或者函数通过OUT或者INOUT范例的参数将数据返回触发器是可以的,但是不能调用直接返回数据的过程。
2.不能再触发器中利用以显示或隐式方式开始或竣事事件的语句,如START TRANS-ACTION,COMMIT或ROLLBACK。
留意事项:MySQL的触发器是按照BEFORE触发器、行利用、AFTER触发器的序次实行的,此中任何一步发生错误都不会继续实行剩下的利用,如果对事件表进行的利用,如果出现错误,那么将会被回滚,如果是对非事件表进行利用,那么就无法回滚了,数据大概会出错。
总结
触发器是基于行触发的,以是删除、新增或者修改利用大概都会激活触发器,以是不要编写过于复杂的触发器,也不要增长过得的触发器,这样会对数据的插入、修改或者删除带来比力严峻的影响,同时也会带来可移植性差的结果,以是在操持触发器的时间肯定要有所考虑。
触发器是一种特别的存储过程,它在插入,删除或修改特定表中的数据时触发实行,它比数据库本身尺度的功能有更精致和更复杂的数据控制本领。
数据库触发器有以下的作用:
1.安全性。可以基于数据库的值利用户具有利用数据库的某种权利。- # 可以基于时间限制用户的操作,例如不允许下班后和节假日修改数据库数据。
- # 可以基于数据库中的数据限制用户的操作,例如不允许股票的价格的升幅一次超过10%。
复制代码
2.审计。可以跟踪用户对数据库的利用。- # 审计用户操作数据库的语句。
- # 把用户对数据库的更新写入审计表。
复制代码
3.实现复杂的数据完备性规则- # 实现非标准的数据完整性检查和约束。触发器可产生比规则更为复杂的限制。与规则不同,触发器可以引用列或数据库对象。例如,触发器可回退任何企图吃进超过自己保证金的期货。
- # 提供可变的缺省值。
复制代码
4.实现复杂的非尺度的数据库相关完备性规则。触发器可以对数据库中相关的表进行连环更新。比方,在auths表author_code列上的删除触发器可导致相应删除在别的表中的与之匹配的行。- # 在修改或删除时级联修改或删除其它表中的与之匹配的行。
- # 在修改或删除时把其它表中的与之匹配的行设成NULL值。
- # 在修改或删除时把其它表中的与之匹配的行级联设成缺省值。
- # 触发器能够拒绝或回退那些破坏相关完整性的变化,取消试图进行数据更新的事务。当插入一个与其主健不匹配的外部键时,这种触发器会起作用。例如,可以在books.author_code列上生成一个插入触发器,如果新值与auths.author_code列中的某值不匹配时,插入被回退。
复制代码
5.同步实时地复制表中的数据。
6.主动计算数据值,如果数据的值到达了肯定的要求,则进行特定的处置惩罚。比方,如果公司的帐号上的资金低于5万元则立即给财政职员发送告诫数据。
无论从事什么行业,只要做好两件事就够了,一个是你的专业、一个是你的品德,专业决定了你的存在,品德决定了你的人脉,剩下的就是对峙,用善良專業和朴拙赢取更多的信托。
本篇文章就到这里了,希望可以或许给你带来资助,也希望您可以或很多多关注草根技术分享的更多内容! |