MySQL Crash Course #17# Chapter 25. 触发器(Trigger)

推荐看这篇 mysql 利用触发器(Trigger)让代码更简单

以及 23.3.1 Trigger Syntax and Examples

 感觉有点像 Spring 里的 AOP

我们为什么需要触发器? -- 因为我们希望当某件事情发生的时候另外一些事情自动发生。。

例如 在向某张表插入数据的时候,同时向另外一张表插入数据。

“向某张表插入数据” 就是事件(导火线),而“向另外一张表插入数据” 就是我们希望自动发生的事情(被触发的事情)。

可是为什么不自己手动“ 先向某表插入数据,再向另外一张表插入数据”呢?

个人觉得,有两个理由促使我们这么做:

  1. 实现某种业务逻辑,就像下了订单一定要减库存对吧? 但是这个活是上层应用程序做还是数据库做是个问题。
  2. 关注点分离。触发事件可以是一些琐碎、业务无关的安全性检查之类的,这个概念可以参考 Spring AOP

下面 COPY 几个 demo 备用。

首先是查看已存在的触发器:

SELECT * FROM information_schema.`TRIGGERS`;

删除已经存在的触发器:

DROP TRIGGER newproduct;

创建一个简单的触发器:

CREATE TRIGGER newproduct AFTER INSERT ON products
FOR EACH ROW SELECT 'Product added';

-- -  每当向 products 插入数据的时候都执行 SELECT 'Product added' ,// 原话打印

- - -- FOR EACH ROW 对于插入的每一条记录都这么做

--- --  PS. 触发器只能创建在实表上,不能创建在虚表上(视图)

-- - - - 每张表至多支持 6 个触发器 AFTER BEFORE 2 * 3 UPDATE DELETE INSERT = 6 

-  ---我尝试了一下居然运行不出来 。。 。 所以,以上规则可能在新版本有变化。。

mysql> CREATE TRIGGER newproduct AFTER INSERT ON products
    -> FOR EACH ROW SELECT 'Product added';
ERROR 1415 (0A000): Not allowed to return a result set from a trigger

 关于触发器的几个注意点:

  1. 触发器不能被覆盖 override ,要修改的话,只能先删除旧的、再创建一个新的。
  2. 在 BEFORE触发器 → SQL语句 → AFTER 触发器这个执行流程中,任何一步出现错误都将不再往下执行。

关于 OLD 和 NEW 关键词

Within the trigger body, the OLD and NEW keywords enable you to access columns in the rows affected by a trigger. OLDand NEW are MySQL extensions to triggers; they are not case-sensitive.

In an INSERT trigger, only NEW.col_name can be used; there is no old row. In a DELETE trigger, only OLD.col_name can be used; there is no new row. In an UPDATE trigger, you can use OLD.col_name to refer to the columns of a row before it is updated and NEW.col_name to refer to the columns of the row after it is updated.

A column named with OLD is read only. You can refer to it (if you have the SELECT privilege), but not modify it. You can refer to a column named with NEW if you have the SELECT privilege for it. In a BEFORE trigger, you can also change its value with SET NEW.col_name = value if you have the UPDATE privilege for it. This means you can use a trigger to modify the values to be inserted into a new row or used to update a row. (Such a SET statement has no effect in an AFTERtrigger because the row change will have already occurred.)

In a BEFORE trigger, the NEW value for an AUTO_INCREMENT column is 0, not the sequence number that is generated automatically when the new row actually is inserted.

触发更多语句

By using the BEGIN ... END construct, you can define a trigger that executes multiple statements.

mysql> delimiter //
mysql> CREATE TRIGGER upd_check BEFORE UPDATE ON account
       FOR EACH ROW
       BEGIN
           IF NEW.amount < 0 THEN
               SET NEW.amount = 0;
           ELSEIF NEW.amount > 100 THEN
               SET NEW.amount = 100;
           END IF;
       END;//
mysql> delimiter ;

猜你喜欢

转载自www.cnblogs.com/xkxf/p/8919828.html