MySQL創建多個觸發器

在本教學中,您將學習如何為MySQL中相同的事件和動作時間創建多個觸發器。

本教程與MySQL5.7.2+版本相關。 如果您有一個較舊版本的MySQL,本教學中的語句將無法正常工作。

MySQL5.7.2+版本之前,您只能為表中的事件創建一個觸發器,例如,只能為BEFORE UPDATEAFTER UPDATE事件創建一個觸發器。 MySQL 5.7.2+版本解決了這樣限制,並允許您為表中的相同事件和動作時間創建多個觸發器。當事件發生時,觸發器將依次啟動。

參考創建第一個觸發器中的語法。如果表中有相同事件有多個觸發器,MySQL將按照創建的順序調用觸發器。要更改觸發器的順序,需要在FOR EACH ROW子句之後指定FOLLOWSPRECEDES。如下說明 -

  • FOLLOWS選項允許新觸發器在現有觸發器之後啟動。
  • PRECEDES選項允許新觸發器在現有觸發器之前啟動。

以下是使用顯式順序創建新的附加觸發器的語法:

DELIMITER $$
CREATE TRIGGER  trigger_name
[BEFORE|AFTER] [INSERT|UPDATE|DELETE] ON table_name
FOR EACH ROW [FOLLOWS|PRECEDES] existing_trigger_name
BEGIN
…

END$$
DELIMITER ;

MySQL多重觸發器示例

我們來看如何一個在表中的同一個事件和動作上,創建多個觸發器的例子。

下麵將使用示例資料庫(zaixiandb)中的products表進行演示。假設,每當更改產品的價格(MSRP列)時,要將舊的價格記錄在一個名為price_logs的表中。

首先,使用CREATE TABLE語句創建一個新的price_logs表,如下所示:

USE zaixiandb;
CREATE TABLE price_logs (
  id INT(11) NOT NULL AUTO_INCREMENT,
  product_code VARCHAR(15) NOT NULL,
  price DOUBLE NOT NULL,
  updated_at TIMESTAMP NOT NULL DEFAULT
             CURRENT_TIMESTAMP
             ON UPDATE CURRENT_TIMESTAMP,

  PRIMARY KEY (id),

  KEY product_code (product_code),

  CONSTRAINT price_logs_ibfk_1 FOREIGN KEY (product_code)
  REFERENCES products (productCode)
  ON DELETE CASCADE
  ON UPDATE CASCADE
);

其次,當表的BEFORE UPDATE事件發生時,創建一個新的觸發器。觸發器名稱為before_products_update,具體實現如下所示:

DELIMITER $$

CREATE TRIGGER before_products_update
   BEFORE UPDATE ON products
   FOR EACH ROW
BEGIN
     INSERT INTO price_logs(product_code,price)
     VALUES(old.productCode,old.msrp);
END$$

DELIMITER ;

第三,我們更改產品的價格,並使用以下UPDATE語句,最後查詢price_logs表:

UPDATE products
SET msrp = 95.1
WHERE productCode = 'S10_1678';
-- 查詢結果價格記錄
SELECT * FROM price_logs;

上面查詢語句執行後,得到以下結果 -

+----+--------------+-------+---------------------+
| id | product_code | price | updated_at          |
+----+--------------+-------+---------------------+
|  1 | S10_1678     |  95.7 | 2017-08-03 02:46:42 |
+----+--------------+-------+---------------------+
1 row in set

可以看到結果中,它按我們預期那樣工作了。

假設不僅要看到舊的價格,改變的時候,還要記錄是誰修改了它。 我們可以向price_logs表添加其他列。 但是,為了實現多個觸發器的演示,我們將創建一個新表來存儲進行更改的用戶的數據。這個新表的名稱為user_change_logs,結構如下:

USE zaixiandb;
CREATE TABLE user_change_logs (
  id int(11) NOT NULL AUTO_INCREMENT,
  product_code varchar(15) DEFAULT NULL,
  updated_at timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP
  ON UPDATE CURRENT_TIMESTAMP,

  updated_by varchar(30) NOT NULL,

  PRIMARY KEY (id),

  KEY product_code (product_code),

  CONSTRAINT user_change_logs_ibfk_1 FOREIGN KEY (product_code)
  REFERENCES products (productCode)
  ON DELETE CASCADE ON UPDATE CASCADE
);

現在,我們創建一個在products表上的BEFORE UPDATE事件上啟動的第二個觸發器。 此觸發器將更改的用戶資訊更新到user_change_logs表。 它在before_products_update觸發後被啟動。

DELIMITER $$
CREATE TRIGGER before_products_update_2
   BEFORE UPDATE ON products
   FOR EACH ROW FOLLOWS before_products_update
BEGIN
   INSERT INTO user_change_logs(product_code,updated_by)
   VALUES(old.productCode,user());
END$$

DELIMITER ;

下麵我們來做一個快速測試。

首先,使用UPDATE語句更新指定產品的價格,如下:

UPDATE products
SET msrp = 95.3
WHERE productCode = 'S10_1678';

其次,分別從price_logsuser_change_logs表查詢數據:

SELECT * FROM price_logs;

上面查詢語句執行後,得到以下結果 -

mysql> SELECT * FROM price_logs;
+----+--------------+-------+---------------------+
| id | product_code | price | updated_at          |
+----+--------------+-------+---------------------+
|  1 | S10_1678     |  95.7 | 2017-08-03 02:46:42 |
|  2 | S10_1678     |  95.1 | 2017-08-03 02:47:21 |
+----+--------------+-------+---------------------+
2 rows in set
SELECT * FROM user_change_logs;

上面查詢語句執行後,得到以下結果 -

mysql> SELECT * FROM user_change_logs;
+----+--------------+---------------------+----------------+
| id | product_code | updated_at          | updated_by     |
+----+--------------+---------------------+----------------+
|  1 | S10_1678     | 2017-08-03 02:47:21 | root@localhost |
+----+--------------+---------------------+----------------+
1 row in set

如上所見,兩個觸發器按照預期的順序啟動執行相關操作了。

觸發器順序

如果使用SHOW TRIGGERS語句,則不會在表中看到觸發啟動同一事件和操作的順序。

SHOW TRIGGERS FROM zaixiandb;

要查找此信息,需要如下查詢information_schema資料庫的triggers表中的action_order列,如下查詢語句 -

SELECT
    trigger_name, action_order
FROM
    information_schema.triggers
WHERE
    trigger_schema = 'zaixiandb'
ORDER BY event_object_table ,
         action_timing ,
         event_manipulation;

上面查詢語句執行後,得到以下結果 -

mysql> SELECT
    trigger_name, action_order
FROM
    information_schema.triggers
WHERE
    trigger_schema = 'zaixiandb'
ORDER BY event_object_table ,
         action_timing ,
         event_manipulation;
+--------------------------+--------------+
| trigger_name             | action_order |
+--------------------------+--------------+
| before_employee_update   |            1 |
| before_products_update   |            1 |
| before_products_update_2 |            2 |
+--------------------------+--------------+
3 rows in set

在本教學中,我們向您展示了如何在MySQL的表中為同一事件創建多個觸發器。


上一篇: MySQL觸發器 下一篇: MySQL管理