触发器是一种特殊类型的存储过程,不由用户直接调用。创建触发器时会对其进行定义,以便在对特定表或列作特定类型的数据修改时执行。触发器可以查询其他表,而且可以包含复杂的 SQL 语句。 它们主要用于强制服从复杂的业务规则或要求。 例如,您可以根据客户当前的帐户状态,控制是否允许插入新订单。
触发器也可用于强制引用完整性,以便在多个表中添加、更新或删除行时,保留在这些表之间所定义的关系
注意:本文的SQL 在 MySQL 8.0版本中测试通过
CREATE
[DEFINER = {user | CURRENT_USER}]
TRIGGER trigger_name
trigger_time trigger_event
ON Table_name FOR EACH ROW
trigger_body
DEFINER:定义可以激活触发器的用户
trigger_time:值只有两个,即before和after,表示触发器执行的时间在事件发生前或发生后
trigger_event:值只有三个,即insert,update和delete,表示触发触发器的事件
ON Table_name:触发器是关联在那个表上的
FOR EACH ROW:表示触发器执行的间隔,这里表示每个修改的记录都会触发触发器
trigger_body:代表触发器所要触发的动作
show triggers;
drop trigger [if exists] trigger_name;
创建如下商品表和订单表,并插入初始商品信息,其中订单的初始编号从1000开始。
create table orders(
order_id INT AUTO_INCREMENT PRIMARY KEY,
good_id INT,
order_number INT
);
alter table orders AUTO_INCREMENT = 1000;
create table goods(
id INT,
name varchar(255),
price FlOAT,
number INT
);
insert into goods values(10001, "cream", 80, 1000);
insert into goods values(10002, "cleanser", 40, 5000);
insert into goods values(10003, "sweater", 99, 13000);
insert into goods values(10004, "honey", 88, 14000);
insert into goods values(10005, "keyboard", 66, 12000);
新增订单时,对订单进行限购处理,每次订单数量小于100,不符合要求时给出相应提示,此时可以创建插入触发器如下:
DELIMITER $;
create trigger order_insert
before insert on orders
for each row
begin
if new.order_number <= 0 then
signal sqlstate '40001' set message_text = 'the order number should more than 0';
set new.order_number = 1;
elseif new.order_number >= 100 then
signal sqlstate '40002' set message_text = 'the order number should less than 100';
set new.order_number = 99;
else
update goods set number = number - new.order_number where id = new.good_id;
end if;
end;
插入数据验证如下:
mysql> insert into orders(good_id, order_number) values(10001, 99);
Query OK, 1 row affected (0.01 sec)
mysql> select * from goods;
+-------+----------+-------+--------+
| id | name | price | number |
+-------+----------+-------+--------+
| 10001 | cream | 80 | 901 |
| 10002 | cleanser | 40 | 5000 |
| 10003 | sweater | 99 | 13000 |
| 10004 | honey | 88 | 14000 |
| 10005 | keyboard | 66 | 12000 |
+-------+----------+-------+--------+
5 rows in set (0.00 sec)
mysql> select * from orders;
+----------+---------+--------------+
| order_id | good_id | order_number |
+----------+---------+--------------+
| 1000 | 10001 | 99 |
+----------+---------+--------------+
1 row in set (0.00 sec)
mysql> insert into orders(good_id, order_number) values(10001, -3);
ERROR 1644 (40001): the order number should more than 0
mysql> insert into orders(good_id, order_number) values(10001, 100);
ERROR 1644 (40002): the order number should less than 100
修改订单信息时,需要对商品信息进行同步处理,此时创建更新触发器如下:
DELIMITER $;
create trigger order_update
before update on orders
for each row
begin
if new.order_number <= 0 then
signal sqlstate '40003' set message_text = 'the order number should more than 0';
set new.order_number = 1;
elseif new.order_number >= 100 then
signal sqlstate '40004' set message_text = 'the order number should less than 100';
set new.order_number = 99;
else
update goods set number = number + old.order_number - new.order_number where id = new.good_id;
end if;
end;
更新数据验证如下:
mysql> update orders set order_number = 199 where order_id = 1000;
ERROR 1644 (40004): the order number should less than 100
mysql> update orders set order_number = -6 where order_id = 1000;
ERROR 1644 (40003): the order number should more than 0
mysql> update orders set order_number = 88 where order_id = 1000;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from goods;
+-------+----------+-------+--------+
| id | name | price | number |
+-------+----------+-------+--------+
| 10001 | cream | 80 | 912 |
| 10002 | cleanser | 40 | 5000 |
| 10003 | sweater | 99 | 13000 |
| 10004 | honey | 88 | 14000 |
| 10005 | keyboard | 66 | 12000 |
+-------+----------+-------+--------+
5 rows in set (0.00 sec)
mysql> select * from orders;
+----------+---------+--------------+
| order_id | good_id | order_number |
+----------+---------+--------------+
| 1000 | 10001 | 88 |
+----------+---------+--------------+
1 row in set (0.00 sec)
当取消订单时,也需要对商品信息进行同步处理,此时创建删除触发器如下:
DELIMITER $;
create trigger order_delete
after delete on orders
for each row
begin
update goods set number = number + old.order_number where id = old.good_id;
end;
删除数据验证如下:
mysql> delete from orders where order_id = 1000;
Query OK, 1 row affected (0.01 sec)
mysql> select * from goods;
+-------+----------+-------+--------+
| id | name | price | number |
+-------+----------+-------+--------+
| 10001 | cream | 80 | 1000 |
| 10002 | cleanser | 40 | 5000 |
| 10003 | sweater | 99 | 13000 |
| 10004 | honey | 88 | 14000 |
| 10005 | keyboard | 66 | 12000 |
+-------+----------+-------+--------+
5 rows in set (0.00 sec)
mysql> select * from orders;
Empty set (0.00 sec)