觸發器(Trigger)是 MySQL 中非常實用的一個功能,它可以在操作者對表進行「增刪改」 之前(或之后)被觸發,自動執行一段事先寫好的 SQL 代碼。
本教程帶領大家在實踐中學習,你將學到觸發器在實際應用場景中的重要應用。
在這個教程中客戶管理系統。在這套系統中,你需要設置在INSERT 表之前檢測操作者是否輸入錯誤數據、在 UPDATE 時,記錄操作者的行為 log ,以及在DELETE 時,判斷刪除的信息是否符合刪除規則。 這三類操作都可以使用 MySQL 觸發器來實現。
下面將詳細講解觸發器全部六種情況:
BEFORE INSERT: 在插入數據前,檢測插入數據是否符合業務邏輯,如不符合返回錯誤信息。AFTER INSERT: 在表 A 創建新賬戶后,將創建成功信息自動寫入表 B 中。BEFORE UPDATE:在更新數據前,檢測更新數據是否符合業務邏輯,如不符合返回錯誤信息。AFTER UPDATE:在更新數據后,將操作行為記錄在 log 中BEFORE DELETE:在刪除數據前,檢查是否有關聯數據,如有,停止刪除操作。AFTER DELETE:刪除表 A 信息后,自動刪除表 B 中與表 A 相關聯的信息。
先決條件
在開始之前,請確保您具備以下條件:
- 一台配置好的 Ubuntu 服務器,root 賬號。
- 服務器上配置好 MySQL Server
- MySQL root 賬號
創建示例數據庫
我們先創建一個干凈的示例數據庫,方便大家可以跟隨本教程一起實踐。我們會在這個數據庫中演示 MySQL 觸發器的多種工作方式。
首先,以 root 身份登錄到你的 MySQL 服務器:
mysql -u root -p
出現提示時,請輸入你 MySQL root 賬號的密碼,然后點擊 ENTER 繼續。看到 mysql> 提示后,運行以下命令,創建 demo_kalacloud 數據庫:
CREATE database demo_kalacloud;
輸出結果
Query OK, 1 row affected (0.00 sec)
接下來,切換到新建的 demo_kalacloud 數據庫:
USE demo_kalacloud;
輸出結果
Database changed
接着創建一個 customers 表。我們使用這個表記錄銀行客戶的信息。這個表包括 customer_id,customer_name,和level。咱們先把客戶分為兩個級別:BASIC和VIP。
create table customers( customer_id BIGINT PRIMARY KEY, customer_name VARCHAR(50), level VARCHAR(50) ) ENGINE=INNODB;
輸出結果
Query OK, 0 rows affected (0.01 sec)
接着,我們向 customers 表中添加一些客戶記錄。
Insert into customers (customer_id, customer_name, level )values('1','Jack Ma','BASIC'); Insert into customers (customer_id, customer_name, level )values('2','Robin Li','BASIC'); Insert into customers (customer_id, customer_name, level )values('3','Pony Ma','VIP');
分別運行三個 INSERT 命令后,命令行輸出成功信息。
輸出結果
Query OK, 1 row affected (0.01 sec)
我們使用 SELECT 檢查一下三條信息是否已經寫入表中:
Select * from customers;
輸出結果

下面我們創建另一個表customer_status,用於保存 customers 表中客戶的備注信息。
這個表包含 customer_id 和 status_notes 字段:
Create table customer_status(customer_id BIGINT PRIMARY KEY, status_notes VARCHAR(50)) ENGINE=INNODB;
然后,我們再創建一個 sales 表,這個表與 customer_id 關聯。保存與客戶有關的銷售數據。
Create table sales(sales_id BIGINT PRIMARY KEY, customer_id BIGINT, sales_amount DOUBLE ) ENGINE=INNODB;
輸出結果:
Query OK, 0 rows affected (0.01 sec)
最后一步,我們再建一個 audit_log 表,用來記錄操作員操作系統時的操作行為。方便管理員在發生問題時,有 log 可查。
Create table audit_log(log_id BIGINT PRIMARY KEY AUTO_INCREMENT, sales_id BIGINT, previous_amount DOUBLE, new_amount DOUBLE, updated_by VARCHAR(50), updated_on DATETIME ) ENGINE=INNODB;
輸出結果
Query OK, 0 rows affected (0.02 sec)
至此,已經把客戶管理系統表建立完成。接下來,我們將對這個管理系統的關鍵節點增加對應的觸發器。
1.BEFORE INSERT 觸發器使用方法
作為嚴謹的管理系統,對任何寫入系統的數據都應該提前檢測,以防止錯誤的信息被寫進去。
在寫入前檢測數據這個功能,我們可以使用BEFORE INSERT 觸發器來實現。
在操作者對 sales 表中的sales_amount 字段進行寫操作時,系統將在寫入(INSERT)前檢查數據是否符合規范。
我們先來看一下,創建觸發器的基本語法。
DELIMITER // CREATE TRIGGER [觸發器的名字] [觸發器執行時機] [觸發器監測的對象] ON [表名] FOR EACH ROW [觸發器主體代碼]// DELIMITER ;
觸發器的結構包括:
DELIMITER //:MySQL 默認分隔符是;但在觸發器中,我們使用//表示觸發器的開始與結束。[觸發器的名字]:這里填寫觸發器的名字[觸發器執行時機]:這里設置觸發器是在關鍵動作執行之前觸發,還是執行之后觸發。[觸發器監測的對象]:觸發器可以監測INSERT、UPDATE、DELETE的操作,當監測的命令對觸發器關聯的表進行操作時,觸發器就被激活了。[表名]:將這個觸發器與數據庫中的表進行關聯,觸發器定義在表上,也附着在表上,如果這個表被刪除了,那么這個觸發器也隨之被刪除。FOR EACH ROW:這句表示只要滿足觸發器觸發條件,觸發器都會被執行,也就是說帶上這個參數后,觸發器將監測每一行對關聯表操作的代碼,一旦符合條件,觸發器就會被觸發。[觸發器主體代碼]:這里是當滿足觸發條件后,被觸發執行的代碼主體。這里可以是一句 SQL 語句,也可以是多行命令。如果是多行命令,那么這些命令要寫在BEGIN...END之間。
注:在創建觸發器主體時,還可以使用OLD和NEW 來獲取 SQL 執行INSERT,UPDATE和DELETE 操作前后的寫入數據。這里沒看明白沒關系,我們將會在接下來的實踐中,展開講解。
講到這里,大家看了一大堆雲里霧里的概念,如果沒看懂,也別擔心。接下來進入實踐環節,只要跟着貼代碼看返回結果,很快你就能夠通透理解觸發器了。
現在,我們來創建第一個觸發器,BEFORE INSERT (在執行 insert 之前,執行觸發器)。這個觸發器用於監測操作者在寫入 sales 表中的 sales_amount 值時,這個值是否大於 10000 ,如果大於,那么返回錯誤信息進行報錯。
登錄 MySQL Server 后,我們創建一個觸發器:
DELIMITER // CREATE TRIGGER validate_sales_amount BEFORE INSERT ON sales FOR EACH ROW IF NEW.sales_amount>10000 THEN SIGNAL SQLSTATE '45000' SET MESSAGE_TEXT = "你輸入的銷售總額超過 10000 元。"; END IF// DELIMITER ;
上面這段代碼中,我們使用IF...THEN...END IF 來創建一個監測 INSERT 語句寫入的值是否在限定的范圍內的觸發器。
這個觸發器的功能時監測 INSERT 在寫入sales_amount 值時,這個新增的(NEW)值是否符合條件( > 10000)。
當操作員錄入一個超過 10000 的數字,會返回如下錯誤信息:
SIGNAL SQLSTATE '45000'
SET MESSAGE_TEXT = '你輸入的銷售總額超過 10000 元。';
我們來試試看,看看觸發器是否已啟用。
我們向 sales_amount 中插入一條 11000 的值。
Insert into sales(sales_id, customer_id, sales_amount) values('1','1','11000');
輸出結果
ERROR 1644 (45000): 你輸入的銷售總額超過 10000 元。
命令行返回錯誤信息,這就是我們剛剛創建觸發器時,填入的錯誤信息。與我們的設置一致。
下面我們 insert 一個值小於 10000 的數字:
Insert into sales(sales_id, customer_id, sales_amount) values('1','1','7700');
輸入值為 7700 小於設定的 10000 ,insert 命令執行成功。
Output Query OK, 1 row affected (0.01 sec)
我們調出 sales 表,看看是否插入成功:
Select * from sales;
輸出確認數據在表中:

通過這張表,我們可以看到,7700 已經插入到表中。
剛剛我們演示了在執行 insert 命令前,檢測某個值是否符合設定,接着我們來看在執行 insert 之后,使用觸發器將不同的值保存到不同的表中。
- AFTER INSERT : 在表 A 創建新賬戶后,將創建成功信息自動寫入表 B 中。
- BEFORE UPDATE :在更新數據前,檢測更新數據是否符合業務邏輯,如不符合返回錯誤信息。
- AFTER UPDATE :在更新數據后,將操作行為記錄在 log 中
- BEFORE DELETE :在刪除數據前,檢查是否有關聯數據,如有,停止刪除操作。
- AFTER DELETE :刪除表 A 信息后,自動刪除表 B 中與表 A 相關聯的信息
