名称 描述 BEFORE 表示在具体的语句执行之前就开始执行触发器的内容 AFTER 表示在具体的语句执行之后才开始执行触发器的内容 {INSERT|DELETE|UPDATE}表示具体的语句,MySQL中目前只支持对INSERT、DELETE、UPDATE这三种类型的语句设置触发器。
FOR EACH ROW BEGIN ... END表示对具体语句影响的每一条记录都执行我们自定义的触发器内容:
对于INSERT语句来说,FOR EACH ROW影响的记录就是我们准备插入的那些新记录。 对于DELETE语句和UPDATE语句来说,FOR EACH ROW影响的记录就是符合WHERE条件的那些记录(如果语句中没有WHERE条件,那就是代表全部的记录)。 小贴士: 如果触发器内容只包含一条语句,那也可以省略BEGN、END这两个词儿。
mysql> delimiter $ mysql> CREATE TRIGGER bi_t1 -> BEFORE INSERT ON t1 -> FOR EACH ROW -> BEGIN -> IF NEW.m1 < 1 THEN -> SET NEW.m1 = 1; -> ELSEIF NEW.m1 > 10 THEN -> SET NEW.m1 = 10; -> END IF; -> END $ Query OK, 0 rows affected (0.02 sec)
触发器使用注意事项 触发器内容中不能有输出结果集的语句。比方说: mysql> delimiter $ mysql> CREATE TRIGGER ai_t1 -> AFTER INSERT ON t1 -> FOR EACH ROW -> BEGIN -> SELECT NEW.m1, NEW.n1; -> END $ ERROR 1415 (0A000): Not allowed to return a result set from a trigger mysql> 显示的ERROR的意思就是不允许在触发器内容中返回结果集! 触发器内容中NEW代表记录的列的值可以被更改,OLD代表记录的列的值无法更改。NEW代表新插入或着即将修改后的记录,修改它的列的值将影响INSERT和UPDATE语句执行后的结果,而OLD代表修改或删除之前的值,我们无法修改它。比方说如果我们非要这么写那就会报错的: mysql> delimiter $ mysql> CREATE TRIGGER bu_t1 -> BEFORE UPDATE ON t1 -> FOR EACH ROW -> BEGIN -> SET OLD.m1 = 1; -> END $ ERROR 1362 (HY000): Updating of OLD row is not allowed in trigger mysql> 可以看到提示的错误中显示在触发器中OLD代表的记录是不可被更改的。 在BEFORE触发器中,我们可以使用SET NEW.列名 = 某个值的形式来更改待插入记录或者待更新记录的某个列的值,但是这种操作不能在AFTER触发器中使用,因为在执行AFTER触发器的内容时记录已经被插入完成或者更新完成了。比方说如果我们非要这么写那就会报错的: mysql> delimiter $ mysql> CREATE TRIGGER ai_t1 -> AFTER INSERT ON t1 -> FOR EACH ROW -> BEGIN -> SET NEW.m1 = 1; -> END $ ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger mysql> 可以看到提示的错误中显示在AFTER触发器中是不允许更改NEW代表的记录的。 如果我们的BEFORE触发器内容执行过程中遇到了错误,那这个触发器对应的具体语句将无法执行;如果具体的操作语句执行过程中遇到了错误,那与它对应的AFTER触发器的内容将无法执行。 小贴士: 对于支持事务的表,不论是执行触发器内容还是具体操作语句过程中出现了错误,会把这个过程中所有的语句都回滚。当然,作为小白的我们并不知道啥是个事务,啥是个回滚,这些进阶内容都在《MySQL是怎样运行的:从根儿上理解MySQL》中呢~ 事件 有时候我们想让MySQL服务器在某个时间点或者每隔一段时间自动地执行一些语句,这时候就需要去创建一个事件。
创建事件 创建事件的语法如下:
CREATE EVENT 事件名 ON SCHEDULE { AT 某个确定的时间点| EVERY 期望的时间间隔 [STARTS datetime][END datetime] } DO BEGIN 具体的语句 END 事件支持两种类型的自动执行方式:
在某个确定的时间点执行。比方说: CREATE EVENT insert_t1_event ON SCHEDULE AT '2019-09-04 15:48:54' DO BEGIN INSERT INTO t1(m1, n1) VALUES(6, 'f'); END 我们在这个事件中指定了执行时间是'2019-09-04 15:48:54',除了直接填某个时间常量,我们也可以填写一些表达式: CREATE EVENT insert_t1 ON SCHEDULE AT DATE_ADD(NOW(), INTERVAL 2 DAY) DO BEGIN INSERT INTO t1(m1, n1) VALUES(6, 'f'); END 其中的DATE_ADD(NOW(), INTERVAL 2 DAY)表示该事件将在当前时间的两天后执行。 每隔一段时间执行一次。比方说: CREATE EVENT insert_t1 ON SCHEDULE EVERY 1 HOUR DO BEGIN INSERT INTO t1(m1, n1) VALUES(6, 'f'); END 其中的EVERY 1 HOUR表示该事件将每隔1个小时执行一次。默认情况下,采用这种每隔一段时间执行一次的方式将从创建事件的事件开始,无限制的执行下去。我们也可以指定该事件开始执行时间和截止时间: CREATE EVENT insert_t1 ON SCHEDULE EVERY 1 HOUR STARTS '2019-09-04 15:48:54' ENDS '2019-09-16 15:48:54' DO BEGIN INSERT INTO t1(m1, n1) VALUES(6, 'f'); END 如上所示,该事件将从'2019-09-04 15:48:54'开始直到'2019-09-16 15:48:54'为止,中间每隔1个小时执行一次。 小贴士: 表示事件间隔的单位除了HOUR,还可以用YEAR、QUARTER、MONTH、DAY、HOUR、 MINUTE、WEEK、SECOND、YEAR_MONTH、DAY_HOUR、DAY_MINUTE、DAY_SECOND、HOUR_MINUTE、HOUR_SECOND、MINUTE_SECOND这些单位,根据具体需求选用我们需要的时间间隔单位。 在创建好事件之后我们就不用管了,到了指定时间,MySQL服务器会帮我们自动执行的。