# 创建before update触发器
DELIMITER $$
CREATE OR REPLACE TRIGGER test.trig_demo5
BEFORE UPDATE ON test.emp FOR EACH ROW
BEGIN
INSERT INTO audit VALUES(NULL,'before update from new',new.emp_no,new.mgr_no,new.emp_name);
INSERT INTO audit VALUES(NULL,'before update from old',old.emp_no,old.mgr_no,old.emp_name);
END$$
DELIMITER ;
# 创建after update触发器
DELIMITER $$
CREATE OR REPLACE TRIGGER test.trig_demo6
AFTER UPDATE ON test.emp FOR EACH ROW
BEGIN
INSERT INTO audit VALUES(NULL,'after update from new',new.emp_no,new.mgr_no,new.emp_name);
INSERT INTO audit VALUES(NULL,'after update from old',old.emp_no,old.mgr_no,old.emp_name);
END$$
DELIMITER ;
before update触发器的作用是:当更新emp表中的一条记录时,首先将表中该行记录插入到old表中,待更新结果插入到new表中,然后激活触发器,向审核表中写入数据,最后修改emp表中的记录。
after update触发器的作用是:当更新emp表中的一条记录时,首先将表中该行记录插入到old表中,待更新结果插入到new表中,然后修改emp表中的记录,最后激活触发器,向审核表中写入数据。
更新emp表中一行记录。
update emp set emp_no=7 where emp_no=8;
查看audit表。
MariaDB [test]> select * from audit;
+----+------------------------+--------+--------+-----------+
| id | note | emp_no | mgr_no | emp_name |
+----+------------------------+--------+--------+-----------+
| 1 | before insert | 10 | 3 | longshuai |
| 2 | after insert | 10 | 3 | longshuai |
| 3 | before delete | 0 | NULL | NULL |
| 4 | after delete | 0 | NULL | NULL |
| 5 | before update from new | 7 | 3 | Monty |
| 6 | before update from old | 8 | 3 | Monty |
| 7 | after update from new | 7 | 3 | Monty |
| 8 | after update from old | 8 | 3 | Monty |
+----+------------------------+--------+--------+-----------+
可以看到,一次update操作触发了before update触发器和after update触发器,并且update操作时,new和old两张表中都有新旧数据。上面的结果中from new对应的是更新后的数据,来源于更新前填充的new表,from old对应的是更新前的旧数据,来源于更新前填充的old表。
5.通过on duplicate key update分析触发器触发原理在MySQL/MariaDB中,如果向表中插入的数据有重复冲突检测时会阻止插入。解决这个问题的其中一个方法就是使用on duplicate key update子句。这个子句应用在insert字句中,但其中涉及到了update操作,那到底会触发哪些触发器呢?
这里先清空上面的audit表。
TRUNCATE audit;
首先测试下使用on duplicate key update子句插入无重复的记录。注意,emp表的emp_no列具有主键属性,它不允许出现重复值。
INSERT INTO emp VALUES(15,5,'xiaofang') ON DUPLICATE KEY UPDATE emp_name='xiaofang';
查看audit表。
MariaDB [test]> select * from audit;
+----+---------------+--------+--------+----------+
| id | note | emp_no | mgr_no | emp_name |
+----+---------------+--------+--------+----------+
| 1 | before insert | 15 | 5 | xiaofang |
| 2 | after insert | 15 | 5 | xiaofang |
+----+---------------+--------+--------+----------+
可以看到,在插入没有重复冲突的行只触发了before insert和after insert触发器。没有触发update触发器。
再插入一条有重复冲突的记录。
TRUNCATE audit;
INSERT INTO emp VALUES(3,1,'xiaofang') ON DUPLICATE KEY UPDATE emp_name='xiaofang';
查看audit表:
MariaDB [test]> select * from audit;
+----+------------------------+--------+--------+----------+
| id | note | emp_no | mgr_no | emp_name |
+----+------------------------+--------+--------+----------+
| 1 | before insert | 3 | 1 | xiaofang |
| 2 | before update from new | 3 | 1 | xiaofang |
| 3 | before update from old | 3 | 1 | Tommy |
| 4 | after update from new | 3 | 1 | xiaofang |
| 5 | after update from old | 3 | 1 | Tommy |
+----+------------------------+--------+--------+----------+