MySQL觸發(fā)器的使用和優(yōu)缺點介紹
前言
在實際開發(fā)中,我們經(jīng)常會遇到這樣的情況:有 2 個或者多個相互關(guān)聯(lián)的表,如 商品信息和庫存信息分別存放在2個不同的數(shù)據(jù)表中,我們在添加一條新商品記錄的時候,為了保證數(shù)據(jù)的完整性,必須同時在庫存表中添加一條庫存記錄。
這樣一來,我們就必須把這兩個關(guān)聯(lián)的操作步驟寫到程序里面,而且要用事務(wù)包裹起來,確保這兩個操作成為一個原子操作 ,要么全部執(zhí)行,要么全部不執(zhí)行。
要是遇到特殊情況,可能還需要對數(shù)據(jù)進行手動維護,這樣就很 容易忘記其中的一步 ,導(dǎo)致數(shù)據(jù)缺失。這個時候,咱們可以使用觸發(fā)器。
你可以創(chuàng)建一個觸發(fā)器,讓商品信息數(shù)據(jù)的插入操作自動觸發(fā)庫存數(shù)據(jù)的插入操作。這樣一來,就不用擔心因為忘記添加庫存數(shù)據(jù)而導(dǎo)致的數(shù)據(jù)缺失了。
1. 觸發(fā)器概述
MySQL從 5.0.2 版本開始支持觸發(fā)器。MySQL的觸發(fā)器和存儲過程一樣,都是嵌入到MySQL服務(wù)器的一段程序。
觸發(fā)器是由事件來觸發(fā)某個操作,這些事件包括 INSERT 、 UPDATE 、 DELETE 事件。所謂事件就是指用戶的動作或者觸發(fā)某項行為。如果定義了觸發(fā)程序,當數(shù)據(jù)庫執(zhí)行這些語句時候,就相當于事件發(fā)生了,就會自動激發(fā)觸發(fā)器執(zhí)行相應(yīng)的操作。當對數(shù)據(jù)表中的數(shù)據(jù)執(zhí)行插入、更新和刪除操作,需要自動執(zhí)行一些數(shù)據(jù)庫邏輯時,可以使用觸發(fā)器來實現(xiàn)。
2. 觸發(fā)器的創(chuàng)建
2.1 創(chuàng)建觸發(fā)器語法
創(chuàng)建觸發(fā)器的語法結(jié)構(gòu)是:
CREATE TRIGGER 觸發(fā)器名稱 {BEFORE|AFTER} {INSERT|UPDATE|DELETE} ON 表名 FOR EACH ROW 觸發(fā)器執(zhí)行的語句塊;
說明:
①表名 :表示觸發(fā)器監(jiān)控的對象。
②BEFORE|AFTER :表示觸發(fā)的時間。BEFORE 表示在事件之前觸發(fā);AFTER 表示在事件之后觸發(fā)。
③INSERT|UPDATE|DELETE :表示觸發(fā)的事件。
INSERT 表示插入記錄;
UPDATE 表示更新記錄;
DELETE 表示刪除記錄。
④觸發(fā)器執(zhí)行的語句塊 :可以是單條SQL語句,也可以是由BEGIN…END結(jié)構(gòu)組成的復(fù)合語句塊。
2.2 代碼舉例
舉例:
①創(chuàng)建數(shù)據(jù)表:
CREATE TABLE test_trigger ( 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) );
②創(chuàng)建觸發(fā)器:創(chuàng)建名稱為before_insert的觸發(fā)器,向test_trigger數(shù)據(jù)表插入數(shù)據(jù)之前,向test_trigger_log數(shù)據(jù)表中插入before_insert的日志信息。
DELIMITER // CREATE TRIGGER before_insert BEFORE INSERT ON test_trigger FOR EACH ROW BEGIN INSERT INTO test_trigger_log (t_log) VALUES('before_insert'); END // DELIMITER ;
③向test_trigger數(shù)據(jù)表中插入數(shù)據(jù)
INSERT INTO test_trigger (t_note) VALUES ('測試 BEFORE INSERT 觸發(fā)器');
④查看test_trigger_log數(shù)據(jù)表中的數(shù)據(jù)
mysql> SELECT * FROM test_trigger_log; +----+---------------+ | id | t_log | +----+---------------+ | 1 | before_insert | +----+---------------+ 1 row in set (0.00 sec)
3. 查看、刪除觸發(fā)器
3.1 查看觸發(fā)器
查看觸發(fā)器是查看數(shù)據(jù)庫中已經(jīng)存在的觸發(fā)器的定義、狀態(tài)和語法信息等。
方式1:查看當前數(shù)據(jù)庫的所有觸發(fā)器的定義
SHOW TRIGGERS\G
方式2:查看當前數(shù)據(jù)庫中某個觸發(fā)器的定義
SHOW CREATE TRIGGER 觸發(fā)器名
方式3:從系統(tǒng)庫information_schema的TRIGGERS表中查詢“salary_check_trigger”觸發(fā)器的信息
SELECT * FROM information_schema.TRIGGERS;
3.2 刪除觸發(fā)器
觸發(fā)器也是數(shù)據(jù)庫對象,刪除觸發(fā)器也用DROP語句,語法格式如下:
DROP TRIGGER IF EXISTS 觸發(fā)器名稱;
4. 觸發(fā)器的優(yōu)缺點
4.1 優(yōu)點
①觸發(fā)器可以確保數(shù)據(jù)的完整性。
假設(shè)我們用 進貨單頭表 (demo.importhead)來保存進貨單的總體信息,包括進貨單編號、供貨商編號、倉庫編號、總計進貨數(shù)量、總計進貨金額和驗收日期。
用 進貨單明細表 (demo.importdetails)來保存進貨商品的明細,包括進貨單編號、商品編號、進貨數(shù)量、進貨價格和進貨金額。
每當我們錄入、刪除和修改一條進貨單明細數(shù)據(jù)的時候,進貨單明細表里的數(shù)據(jù)就會發(fā)生變動。這個時候,在進貨單頭表中的總計數(shù)量和總計金額就必須重新計算,否則,進貨單頭表中的總計數(shù)量和總計金額就不等于進貨單明細表中數(shù)量合
計和金額合計了,這就是數(shù)據(jù)不一致。
為了解決這個問題,我們就可以使用觸發(fā)器,規(guī)定每當進貨單明細表有數(shù)據(jù)插入、修改和刪除的操作時,自動觸發(fā) 2 步操作:
1)重新計算進貨單明細表中的數(shù)量合計和金額合計;
2)用第一步中計算出來的值更新進貨單頭表中的合計數(shù)量與合計金額。
這樣一來,進貨單頭表中的合計數(shù)量與合計金額的值,就始終與進貨單明細表中計算出來的合計數(shù)量與合計金額的值相同,數(shù)據(jù)就是一致的,不會互相矛盾。
②觸發(fā)器可以幫助我們記錄操作日志。
利用觸發(fā)器,可以具體記錄什么時間發(fā)生了什么。比如,記錄修改會員儲值金額的觸發(fā)器,就是一個很好的例子。這對我們還原操作執(zhí)行時的具體場景,更好地定位問題原因很有幫助。
③觸發(fā)器還可以用在操作數(shù)據(jù)前,對數(shù)據(jù)進行合法性檢查。
比如,超市進貨的時候,需要庫管錄入進貨價格。但是,人為操作很容易犯錯誤,比如說在錄入數(shù)量的時候,把條形碼掃進去了;錄入金額的時候,看串了行,錄入的價格遠超售價,導(dǎo)致賬面上的巨虧。這些都可以通過觸發(fā)器,在實際插入
或者更新操作之前,對相應(yīng)的數(shù)據(jù)進行檢查,及時提示錯誤,防止錯誤數(shù)據(jù)進入系統(tǒng)。
4.2 缺點
①觸發(fā)器最大的一個問題就是可讀性差。
因為觸發(fā)器存儲在數(shù)據(jù)庫中,并且由事件驅(qū)動,這就意味著觸發(fā)器有可能 不受應(yīng)用層的控制 。這對系統(tǒng)維護是非常有挑戰(zhàn)的。比如,創(chuàng)建觸發(fā)器用于修改會員儲值操作。如果觸發(fā)器中的操作出了問題,會導(dǎo)致會員儲值金額更新失敗。我用
下面的代碼演示一下:
mysql> update demo.membermaster set memberdeposit=20 where memberid = 2; ERROR 1054 (42S22): Unknown column 'aa' in 'field list'
結(jié)果顯示,系統(tǒng)提示錯誤,字段“aa”不存在。這是因為,觸發(fā)器中的數(shù)據(jù)插入操作多了一個字段,系統(tǒng)提示錯誤??墒?,如果你不了解這個觸發(fā)器,很可能會認為是更新語句本身的問題,或者是會員信息表的結(jié)構(gòu)出了問題。說不定你還會給
會員信息表添加一個叫“aa”的字段,試圖解決這個問題,結(jié)果只能是白費力。
②相關(guān)數(shù)據(jù)的變更,可能會導(dǎo)致觸發(fā)器出錯。
特別是數(shù)據(jù)表結(jié)構(gòu)的變更,都可能會導(dǎo)致觸發(fā)器出錯,進而影響數(shù)據(jù)操作的正常運行。這些都會由于觸發(fā)器本身的隱蔽性,影響到應(yīng)用中錯誤原因排查的效率。
4.3 注意點
注意,如果在子表中定義了外鍵約束,并且外鍵指定了ON UPDATE/DELETE CASCADE/SET NULL子句,此時修改父表被引用的鍵值或刪除父表被引用的記錄行時,也會引起子表的修改和刪除操作,此時基于子表的UPDATE和DELETE語
句定義的觸發(fā)器并不會被激活。
到此這篇關(guān)于MySQL觸發(fā)器的使用和優(yōu)缺點介紹的文章就介紹到這了,更多相關(guān)MySQL觸發(fā)器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章

Mysql數(shù)據(jù)庫中數(shù)字相減 出現(xiàn)負數(shù)時sql 語句報錯的問題

MYSQL 左連接右連接和內(nèi)連接的詳解及區(qū)別