共計 3879 個字符,預計需要花費 10 分鐘才能閱讀完成。
這篇文章主要介紹“MySQL 觸發器怎么創建和使用”,在日常操作中,相信很多人在 MySQL 觸發器怎么創建和使用問題上存在疑惑,丸趣 TV 小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”MySQL 觸發器怎么創建和使用”的疑惑有所幫助!接下來,請跟著丸趣 TV 小編一起來學習吧!
在實際開發中,我們經常會遇到這樣的情況:有 2 個或者多個相互關聯的表,如 商品信息 和 庫存信息 分 別存放在 2 個不同的數據表中,我們在添加一條新商品記錄的時候,為了保證數據的完整性,必須同時 在庫存表中添加一條庫存記錄。這樣一來,我們就必須把這兩個關聯的操作步驟寫到程序里面,而且要用 事務 包裹起來,確保這兩個操 作成為一個 原子操作,要么全部執行,要么全部不執行。
要是遇到特殊情況,可能還需要對數據進行手 動維護,這樣就很 容易忘記其中的一步,導致數據缺失。這個時候,咱們可以使用觸發器。你可以創建一個觸發器,讓商品信息數據的插入操作自動觸發庫存數 據的插入操作。這樣一來,就不用擔心因為忘記添加庫存數據而導致的數據缺失了。
觸發器概述
MySQL 從 5 . 0 . 2 版本開始支持觸發器。MySQL 的觸發器和存儲過程一樣,都是嵌入到 MySQL 服務器的一 段程序。觸發器是由 事件來觸發 某個操作,這些事件包括 INSERT、UPDATE、DELETE 事件。
所謂事件就是指 用戶的動作或者觸發某項行為。如果定義了觸發程序,當數據庫執行這些語句時候,就相當于事件發生 了,就會 自動 激發觸發器執行相應的操作。當對數據表中的數據執行插入、更新和刪除操作,需要自動執行一些數據庫邏輯時,可以使用觸發器來 實現。
觸發器的創建
創建觸發器語法
CREATE TRIGGER 觸發器名稱
{BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名
FOR EACH ROW
觸發器執行的語句塊;
說明:
表名:表示觸發器監控的對象。
BEFORE | AFTER:表示觸發的時間。BEFORE 表示在事件之前觸發;AFTER 表示在事件之后觸發。
INSERT | UPDATE | DELETE:表示觸發的事件。
INSERT 表示插入記錄時觸發;
UPDATE 表示更新記錄時觸發;
DELETE 表示刪除記錄時觸發。
代碼舉例 1
創建倆張表
CREATE TABLE test_trigge r (
id INT PRIMARY KEY AUTO_INCREMENT ,
t_note VARCHAR ( 30 )
) ;
CREATE TABLE test_trigger_log (
id INT PRIMARY KEY AUTO_INCREMENT ,
t_log VARCHAR ( 30 )
) ;
創建觸發器
DELIMITER / /
CREATE TRIGGER befo_re_insert
BEFORE INSERT ON test_trigger
FOR EACH ROW
BEGIN
INSERT INTO test_trigger_log ( t_log )
VALUES ( befo re_inse rt ) ;
END / /
DELIMITER ;
向 test_trigger 數據表中插入數據
INSERT INTO test_trigger (t_note) VALUES (測試 BEFORE INSERT 觸發器
查看 test_trigger_log 數據表中的數據
SELECT * FROM test_trigger_log
代碼舉例 2
創建觸發器
DELIMITER / /
CREATE TRIGGER after_insert
AFTER INSERT ON test_trigger
FOR EACH ROW
BEGIN
INSERT INTO test_trigger_log ( t_log )
VALUES ( after_insert ) ;
END / /
DELIMITER ;
向 test_trigger 數據表中插入數據。
INSERT INTO test_trigger (t_note) VALUES (測試 AFTER INSERT 觸發器
查看 test_trigger_log 數據表中的數據
SELECT * FROM test_trigger_log
代碼舉例 3
定義觸發器“salary_check_trigger”,基于員工表“employees”的 INSERT 事件,在 INSERT 之前檢查將要添加的新員工薪資是否大于他領導的薪資,如果大于領導薪資,則報 sqlstate_value 為 HY000 的錯誤,從而使得添加失敗。
DELIMITER //
CREATE TRIGGER salary_check_trigger
BEFORE INSERT ON employees FOR EACH ROW
BEGIN
DECLARE mgrsalary DOUBLE;
SELECT salary INTO mgrsalary FROM employees WHERE employee_id = NEW.manager_id;
IF NEW.salary mgrsalary THEN
SIGNAL SQLSTATE HY000 SET MESSAGE_TEXT = 薪資高于領導薪資錯誤
END IF;
END //
DELIMITER ;
上面觸發器聲明過程中的 NEW 關鍵字代表 INSERT 添加語句的新記錄。
查看刪除觸發器
方式 1:查看當前數據庫的所有觸發器的定義
SHOW TRIGGERS
方式 2:查看當前數據庫中某個觸發器的定義方式
SHOW CREATE TRIGGER 觸發器名
方式 3:從系統庫 information_schema 的 TRIGGERS 表中查詢“salary_check_trigger”觸發器的信息。
SELECT * FROM information_schema.TRIGGERS;
刪除觸發器
DROP TRIGGER IF EXISTS 觸發器名稱
觸發器的優點
1、觸發器可以確保數據的完整性。
假設我們用 進貨單頭表(demo.importhead)來保存進貨單的總體信息,包括進貨單編號、供貨商編號、倉庫編號、總計進貨數量、總計進貨金額和驗收日期。
用 進貨單明細表(demo.importdetails)來保存進貨商品的明細,包括進貨單編號、商品編號、進貨數
量、進貨價格和進貨金額額就不等于進貨單明細表中數量合計和金額合計了,這就是數據不一致。
為了解決這個問題,我們就可以使用觸發器,規定每當進貨單明細表有數據插入、修改和刪除的操作
時,自動觸發 2 步操作:
1)重新計算進貨單明細表中的數量合計和金額合計;
2)用第一步中計算出來的值更新進貨單頭表中的合計數量與合計金額。
這樣一來,進貨單頭表中的合計數量與合計金額的值,就始終與進貨單明細表中計算出來的合計數量與
合計金額的值相同,數據就是一致的,不會互相矛盾。
2、觸發器可以幫助我們記錄操作日志。
利用觸發器,可以具體記錄什么時間發生了什么。比如,記錄修改會員儲值金額的觸發器,就是一個很
好的例子。這對我們還原操作執行時的具體場景,更好地定位問題原因很有幫助。
3、觸發器還可以用在操作數據前,對數據進行合法性檢查。
比如,超市進貨的時候,需要庫管錄入進貨價格。但是,人為操作很容易犯錯誤,比如說在錄入數量的
時候,把條形碼掃進去了;錄入金額的時候,看串了行,錄入的價格遠超售價,導致賬面上的巨虧 ……
這些都可以通過觸發器,在實際插入或者更新操作之前,對相應的數據進行檢查,及時提示錯誤,防止
錯誤數據進入系統。
觸發器的缺點
1、觸發器最大的一個問題就是可讀性差。
因為觸發器存儲在數據庫中,并且由事件驅動,這就意味著觸發器有可能 不受應用層的控制。這對系統維護是非常有挑戰的。
比如,創建觸發器用于修改會員儲值操作。如果觸發器中的操作出了問題,會導致會員儲值金額更新失敗。我用下面的代碼演示一下
結果顯示,系統提示錯誤,字段“aa”不存在。
這是因為,觸發器中的數據插入操作多了一個字段,系統提示錯誤。可是,如果你不了解這個觸發器,很可能會認為是更新語句本身的問題,或者是會員信息表的結構出了問題。說不定你還會給會員信息表添加一個叫“aa”的字段,試圖解決這個問題,結果只能是白費力。
2、相關數據的變更,可能會導致觸發器出錯。
特別是數據表結構的變更,都可能會導致觸發器出錯,進而影響數據操作的正常運行。這些都會由于觸發器本身的隱蔽性,影響到應用中錯誤原因排查的效率。
注意點
注意,如果在子表中定義了外鍵約束,并且外鍵指定了 ON UPDATE/DELETE CASCADE/SET NULL 子句,此時修改父表被引用的鍵值或刪除父表被引用的記錄行時,也會引起子表的修改和刪除操作,此時基于子表的 UPDATE 和 DELETE 語句定義的觸發器并不會被激活。
例如:基于子表員工表(t_employee)的 DELETE 語句定義了觸發器 t1,而子表的部門編號(did)字段定義了外鍵約束引用了父表部門表(t_department)的主鍵列部門編號(did),并且該外鍵加了“ONDELETE SET NULL”子句,那么如果此時刪除父表部門表(t_department)在子表員工表(t_employee)
到此,關于“MySQL 觸發器怎么創建和使用”的學習就結束了,希望能夠解決大家的疑惑。理論與實踐的搭配能更好的幫助大家學習,快去試試吧!若想繼續學習更多相關知識,請繼續關注丸趣 TV 網站,丸趣 TV 小編會繼續努力為大家帶來更多實用的文章!