MySQL学习--触发器

触发器

文章目录

  • 触发器
    • 触发器基本概念
      • 触发器应用场景:
    • 触发器创建语句四要素:
      • 简单的触发器创建
    • 行变量
    • 触发器的简单编程
      • before和after 的区别
    • for each row

触发器基本概念

触发器定义:是一类特殊的事务。可以监视某种数据操作(insert/update/delete)。并触发相关数据操作(insert/update/delete)。

触发器应用场景:

1.当向一张表中添加或删除记录时,需要在相关表中进行同步操作。比如,当一个订单产生时,订单所购的商品的库存量相应减少。

2.当表上某列数据的值与其他表中的数据有联系时。比如,当某客户进行欠款消费,可以在生成订单时通过设计触发器判断该客户的累计欠款是否超出了最木限度。

3.当需要对某张表进行跟踪时。比如,当有新订单产生时,需要及时通知相关人员进行处理,此时可以在订单表上设计添加触发器加以实现。

触发器创建语句四要素:

  • 1.监视地点(table)
  • 2.监视事件(insert/update/delete)
  • 3.触发时间(after/before)
  • 4.触发事件(insert/update/delete)

简单的触发器创建

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变量

MySQL学习--触发器_第1张图片
MySQL学习--触发器_第2张图片

需求:

商品表: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。

before和after 的区别

ERROR 1362 (HY000): Updating of NEW row is not allowed in after trigger

原因:insert之后,new已经插入表中,再改new为时已晚。

  • before:在监视事件为完成之前进行触发事件
  • after:在监视事件完成后进行处罚事件
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)

for each row

在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)

你可能感兴趣的:(SQL学习)