触发器定义:是一类特殊的事务。可以监视某种数据操作(insert/update/delete)。并触发相关数据操作(insert/update/delete)。
1.当向一张表中添加或删除记录时,需要在相关表中进行同步操作。比如,当一个订单产生时,订单所购的商品的库存量相应减少。
2.当表上某列数据的值与其他表中的数据有联系时。比如,当某客户进行欠款消费,可以在生成订单时通过设计触发器判断该客户的累计欠款是否超出了最木限度。
3.当需要对某张表进行跟踪时。比如,当有新订单产生时,需要及时通知相关人员进行处理,此时可以在订单表上设计添加触发器加以实现。
mysql> delimiter $
mysql> create trigger t1
-> after
-> insert on ord
-> for each row
-> begin
-> update goods set num=num-2 where gid=1;
-> end$
Query OK, 0 rows affected (0.82 sec)
mysql> show triggers \G
*************************** 1. row ***************************
Trigger: t1
Event: INSERT
Table: ord
Statement: begin
update goods set num=num-2 where gid=1;
end
Timing: AFTER
Created: 2021-04-20 19:16:54.72
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
Database Collation: utf8mb4_0900_ai_ci
1 row in set (0.00 sec)
insert:只有new变量
delete:只有old变量
update:既有old变量又有new变量
需求:
商品表:goods
订单表:ord
下一个订单,仓库存储就减少相应的数量
mysql> create trigger t2
-> after insert on ord
-> for each row
-> begin
-> update goods set num = num-new.much where gid=new.gid;
-> end$
Query OK, 0 rows affected (0.49 sec)
mysql> drop trigger t1;
-> $
Query OK, 0 rows affected (0.24 sec)
mysql> show triggers \G
*************************** 1. row ***************************
Trigger: t2
Event: INSERT
Table: ord
Statement: begin
update goods set num = num-new.much where gid=new.gid;
end
Timing: AFTER
Created: 2021-04-20 19:27:33.64
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
Database Collation: utf8mb4_0900_ai_ci
1 row in set (0.10 sec)
mysql> select * from goods;
-> $
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 40 |
| 2 | dog | 62 |
| 3 | pig | 33 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> delimiter ;
mysql>
mysql>
mysql> select * from goods;
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 40 |
| 2 | dog | 62 |
| 3 | pig | 33 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> insert into ord values (123,2,3);
Query OK, 1 row affected (0.05 sec)
mysql> select * from goods;
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 40 |
| 2 | dog | 59 |
| 3 | pig | 33 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> insert into ord values (123,3,3);
Query OK, 1 row affected (0.12 sec)
mysql> select * from goods;
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 40 |
| 2 | dog | 59 |
| 3 | pig | 30 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> create trigger t1
-> after insert on ord
-> for each row
-> begin
-> update goods set num = num-2 where gid=1;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 5
mysql> end$
-> ;
ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'end$' at line 1
mysql> delimiter $
mysql> create trigger t1
-> after insert on ord
-> for each row
-> begin
-> update goods set num = num-2 where gid=1;
-> end$
Query OK, 0 rows affected (0.14 sec)
mysql> select * from goods;
-> $
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 40 |
| 2 | dog | 59 |
| 3 | pig | 30 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> insert ord values (125,1,5)$
Query OK, 1 row affected (0.10 sec)
mysql> select * from goods;
-> $
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 33 |
| 2 | dog | 59 |
| 3 | pig | 30 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> show triggers \G
*************************** 1. row ***************************
Trigger: t2
Event: INSERT
Table: ord
Statement: begin
update goods set num = num-new.much where gid=new.gid;
end
Timing: AFTER
Created: 2021-04-20 19:27:33.64
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
Database Collation: utf8mb4_0900_ai_ci
*************************** 2. row ***************************
Trigger: t1
Event: INSERT
Table: ord
Statement: begin
update goods set num = num-2 where gid=1;
end
Timing: AFTER
Created: 2021-04-20 19:32:18.79
sql_mode: ONLY_FULL_GROUP_BY,STRICT_TRANS_TABLES,ERROR_FOR_DIVISION_BY_ZERO,NO_ENGINE_SUBSTITUTION
Definer: root@localhost
character_set_client: utf8mb4
collation_connection: utf8mb4_0900_ai_ci
Database Collation: utf8mb4_0900_ai_ci
2 rows in set (0.00 sec)
mysql> create trigger t3
-> after delete on ord
-> for each row
-> begin
-> update goods set num = num+old.much where gid=old.gid;
-> end$
Query OK, 0 rows affected (0.24 sec)
mysql> delete from ord where oid=125$
Query OK, 1 row affected (0.05 sec)
mysql> select * from goods$
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 24 |
| 2 | dog | 59 |
| 3 | pig | 30 |
+------+------+------+
3 rows in set (0.00 sec)
可以发现mysql现版本是支持对同一个监视地点,监视时间,触发时间,进行不同的触发操作的。(两个触发操作会进行叠加)
改订单数量(仅限改数量)
mysql> create trigger t4
-> before update on ord
-> for each row
-> begin
-> update goods set num = num +old.much-new.much where gid=new.gid;
-> end $
Query OK, 0 rows affected (0.73 sec)
mysql>
mysql>
mysql>
mysql> select * from goods$
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 24 |
| 2 | dog | 59 |
| 3 | pig | 30 |
+------+------+------+
3 rows in set (0.11 sec)
mysql> select * from ord$
+------+------+------+
| oid | gid | much |
+------+------+------+
| 123 | 2 | 3 |
| 123 | 3 | 3 |
+------+------+------+
2 rows in set (0.11 sec)
mysql> update ord set much = 2 where oid=123$
Query OK, 2 rows affected (0.19 sec)
Rows matched: 2 Changed: 2 Warnings: 0
mysql> select * from goods$
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 24 |
| 2 | dog | 60 |
| 3 | pig | 31 |
+------+------+------+
3 rows in set (0.00 sec)
如果剩余3头猪,但客户买了10头猪,发生什么情况?能否预防能否在购买量much >库存量num时,把much自动改为num。
ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
原因:insert之后,new已经插入表中,再改new为时已晚。
mysql> create trigger t2
-> after insert on ord
->
-> for each row
-> begin
-> declare rnum int;
-> select num into rnum from goods where gid = new.gid;
->
-> if new.much>rnum then
-> set new.much = rnum;
-> end if;
->
->
-> update goods set num = num-new.much where gid=new.gid;
-> end$
ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger
mysql> create trigger t2
-> before insert on ord
->
-> for each row
-> begin
-> declare rnum int;
-> select num into rnum from goods where gid = new.gid;
->
-> if new.much>rnum then
-> set new.much = rnum;
-> end if;
->
->
-> update goods set num = num-new.much where gid=new.gid;
-> end$
Query OK, 0 rows affected (0.37 sec)
mysql> insert into ord values (124,1,10);
-> $
Query OK, 1 row affected (0.24 sec)
mysql> select * from goods$
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 14 |
| 2 | dog | 60 |
| 3 | pig | 31 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> insert into ord values (125,1,20)$
Query OK, 1 row affected (0.06 sec)
mysql> select * from goods$
+------+------+------+
| gid | name | num |
+------+------+------+
| 1 | cat | 0 |
| 2 | dog | 60 |
| 3 | pig | 31 |
+------+------+------+
3 rows in set (0.00 sec)
mysql> select * from ord;
-> $
+------+------+------+
| oid | gid | much |
+------+------+------+
| 124 | 1 | 10 |
| 123 | 2 | 2 |
| 123 | 3 | 2 |
| 125 | 1 | 14 |
+------+------+------+
4 rows in set (0.00 sec)
在oracle中,触发器分为语句级触发器和行级触发器。在mysql中仅支持行级触发器。
for each row:表示每一行受影响,触发器都会执行,叫做行级触发器
在oracle中,for each row 如果不写,无论update语句一次影响多少行,都只执行一次。
mysql> create table tmp(
-> id int
-> )engine myisam charset utf8;
-> $
Query OK, 0 rows affected, 1 warning (0.21 sec)
mysql> create trigger t5 before update on ord
-> for each row
-> begin
-> insert into tmp values (5);
-> end$
Query OK, 0 rows affected (0.15 sec)
mysql> select * from ord;
-> $
+------+------+------+
| oid | gid | much |
+------+------+------+
| 124 | 1 | 10 |
| 123 | 2 | 2 |
| 123 | 3 | 2 |
| 125 | 1 | 14 |
+------+------+------+
4 rows in set (0.00 sec)
mysql> update ord set much =2 $
Query OK, 2 rows affected (0.07 sec)
Rows matched: 4 Changed: 2 Warnings: 0
mysql> select * from tmp$
+------+
| id |
+------+
| 5 |
| 5 |
| 5 |
| 5 |
+------+
4 rows in set (0.00 sec)