從零開始MySQL觸發(fā)器實(shí)戰(zhàn)攻略
在學(xué)習(xí) MySQL 的過(guò)程中,可能你了解過(guò)觸發(fā)器的概念,不清楚各位是否有詳細(xì)的去學(xué)習(xí)過(guò)觸發(fā)器,最近看了幾篇關(guān)于觸發(fā)器的文檔,分享下 MySQL 觸發(fā)器相關(guān)知識(shí)。
1.觸發(fā)器簡(jiǎn)介
觸發(fā)器即 triggers ,它是與表有關(guān)的數(shù)據(jù)庫(kù)對(duì)象,在滿足定義條件時(shí)觸發(fā),并執(zhí)行觸發(fā)器中定義的語(yǔ)句集合。它的執(zhí)行不是由程序調(diào)用,也不是手工啟動(dòng),而是由事件來(lái)觸發(fā),比如當(dāng)對(duì)一個(gè)表進(jìn)行操作( insert,delete, update)時(shí)就會(huì)激活它執(zhí)行。觸發(fā)器經(jīng)常用于加強(qiáng)數(shù)據(jù)的完整性約束和業(yè)務(wù)規(guī)則等。
參考官方文檔,觸發(fā)器創(chuàng)建語(yǔ)法模板如下:
CREATE [DEFINER = user] TRIGGER trigger_name trigger_time trigger_event ON tbl_name FOR EACH ROW [trigger_order] trigger_body trigger_time: { BEFORE | AFTER } trigger_event: { INSERT | UPDATE | DELETE } trigger_order: { FOLLOWS | PRECEDES } other_trigger_name
觸發(fā)器只能創(chuàng)建在永久表上,不能對(duì)臨時(shí)表或視圖創(chuàng)建觸發(fā)器。觸發(fā)器的名稱在單個(gè)數(shù)據(jù)庫(kù)內(nèi)是唯一的。參考上面創(chuàng)建語(yǔ)句,觸發(fā)器創(chuàng)建有幾點(diǎn)要素,下面簡(jiǎn)要說(shuō)明下:
trigger_time:是觸發(fā)動(dòng)作時(shí)間,可以是 BEFORE 或 AFTER ,表示觸發(fā)器在要修改的每一行之前或之后激活。
trigger_event:指示激活觸發(fā)器的操作類型。這些 trigger_event 值是被允許的:
- insert:只要向表中插入新行,觸發(fā)器就會(huì)激活。例如 insert 、load data、replace 語(yǔ)句。
- update:更改表中某一行數(shù)據(jù)時(shí)激活觸發(fā)器。例如 update 語(yǔ)句。
- delete:從表中刪除某一行數(shù)據(jù)時(shí)激活觸發(fā)器。例如 delete 和 replace 語(yǔ)句。表上的 DROP TABLE 和 TRUNCATE TABLE 語(yǔ)句不會(huì)激活此觸發(fā)器,因?yàn)樗鼈儾皇褂?delete ,刪除分區(qū)也不會(huì)激活 delete 觸發(fā)器。
trigger_body:是觸發(fā)器激活時(shí)要執(zhí)行的語(yǔ)句。如果要執(zhí)行多個(gè)語(yǔ)句,可使用 BEGIN…END 復(fù)合語(yǔ)句結(jié)構(gòu)。在觸發(fā)器主體中,可以使用 old 和 new 來(lái)引用觸發(fā)器中發(fā)生變化的記錄內(nèi)容。
2.觸發(fā)器具體操作
下面來(lái)看下觸發(fā)器相關(guān)的具體操作:
# 創(chuàng)建表 創(chuàng)建觸發(fā)器 mysql> CREATE TABLE account (acct_num INT, amount DECIMAL(10,2)); Query OK, 0 rows affected (0.03 sec) mysql> INSERT INTO account VALUES(137,14.98),(141,1937.50),(97,-100.00); 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 ; # 驗(yàn)證觸發(fā)器作用 mysql> select * from account; +----------+---------+ | acct_num | amount | +----------+---------+ | 137 | 14.98 | | 141 | 1937.50 | | 97 | -100.00 | +----------+---------+ 3 rows in set (0.00 sec) mysql> update account set amount = 114.98 where acct_num = 137; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> select * from account; +----------+---------+ | acct_num | amount | +----------+---------+ | 137 | 100.00 | | 141 | 1937.50 | | 97 | -100.00 | +----------+---------+ 3 rows in set (0.00 sec) # 查看觸發(fā)器 mysql> show triggers; # 刪除觸發(fā)器 mysql> drop trigger if exists upd_check; # 查看數(shù)據(jù)庫(kù)實(shí)例中所有觸發(fā)器 SELECT a.TRIGGER_SCHEMA, a.TRIGGER_NAME, a.ACTION_TIMING, a.EVENT_OBJECT_TABLE, a.EVENT_MANIPULATION FROM information_schema.`TRIGGERS` a WHERE a.TRIGGER_SCHEMA NOT IN ( 'information_schema', 'performance_schema', 'mysql', 'sys' ); delimiter // 設(shè)置MySQL執(zhí)行結(jié)束標(biāo)志,默認(rèn)為;
上面展示了一些關(guān)于觸發(fā)器的基本操作,其實(shí)觸發(fā)器在生產(chǎn)環(huán)境中還是比較少見(jiàn)的,即使它能解決我們某些數(shù)據(jù)庫(kù)需求,因?yàn)橛|發(fā)器的使用存在一系列的缺點(diǎn),簡(jiǎn)要總結(jié)幾點(diǎn)缺點(diǎn)如下:
- 使用觸發(fā)器實(shí)現(xiàn)的業(yè)務(wù)邏輯在出現(xiàn)問(wèn)題時(shí)很難進(jìn)行定位,特別是涉及到多個(gè)觸發(fā)器的情況下,會(huì)使后期維護(hù)變得困難。
- 大量使用觸發(fā)器容易導(dǎo)致代碼結(jié)構(gòu)被打亂,增加了程序的復(fù)雜性,
- 如果需要變動(dòng)的數(shù)據(jù)量較大時(shí),觸發(fā)器的執(zhí)行效率會(huì)非常低。
- 觸發(fā)器隱式調(diào)用容易被忽略,出現(xiàn)問(wèn)題不好排查。
但是觸發(fā)器也并不是一無(wú)用處,比如我們不想讓人刪除或更新這個(gè)表的數(shù)據(jù),可以用觸發(fā)器實(shí)現(xiàn),下面的一些場(chǎng)景可能對(duì)你有所啟發(fā):
# 禁止刪除數(shù)據(jù) 即使你有權(quán)限 mysql> select * from student; +--------------+------+--------+-------+-------+ | increment_id | s_id | s_name | s_sex | s_age | +--------------+------+--------+-------+-------+ | 1 | 1001 | sdfsd | 男 | 18 | | 2 | 1003 | zsdfsd | 女 | 19 | +--------------+------+--------+-------+-------+ 2 rows in set (0.00 sec) mysql> delimiter // mysql> CREATE TRIGGER `tri_delstu` BEFORE DELETE ON `student` FOR EACH ROW begin -> declare msg varchar(255); -> set msg="不允許刪除學(xué)生信息"; -> SIGNAL SQLSTATE 'HY000' SET MESSAGE_TEXT = msg; -> end; // Query OK, 0 rows affected (0.02 sec) mysql> delimiter ; mysql> delete from student where s_id = 1003; ERROR 1644 (HY000): 不允許刪除學(xué)生信息 # 禁止更新某個(gè)字段 mysql> delimiter // mysql> CREATE TRIGGER trg__updateSid BEFORE UPDATE ON `student` -> FOR EACH ROW -> BEGIN -> DECLARE msg VARCHAR(100); -> IF NEW.s_id <> OLD.s_id THEN -> SET msg='不允許修改學(xué)號(hào)'; -> SIGNAL SQLSTATE 'HY000' SET message_text = msg; -> END IF; -> END; // Query OK, 0 rows affected (0.06 sec) mysql> delimiter ; mysql> update student set s_id = 1002 where increment_id = 2; ERROR 1644 (HY000): 不允許修改學(xué)號(hào) # 限制修改范圍 mysql> delimiter // mysql> CREATE TRIGGER `tri_update_age` BEFORE UPDATE ON `student` FOR EACH ROW BEGIN -> DECLARE msg VARCHAR(20); -> IF (NEW.s_age<0) THEN -> set msg="年齡不能小于0"; -> signal sqlstate 'HY000' set message_text=msg; -> END IF; -> END; // Query OK, 0 rows affected (0.02 sec) mysql> delimiter ; mysql> update student set s_age=10 where s_id = 1001; Query OK, 1 row affected (0.01 sec) Rows matched: 1 Changed: 1 Warnings: 0 mysql> update student set s_age=-10 where s_id = 1001; ERROR 1644 (HY000): 年齡不能小于0
總結(jié):
本篇文章簡(jiǎn)要介紹了觸發(fā)器的定義及使用案例。在業(yè)務(wù)邏輯復(fù)雜或表變動(dòng)比較頻繁的系統(tǒng)還是不推薦使用觸發(fā)器,當(dāng)然它也是有自己的應(yīng)用場(chǎng)景,無(wú)論怎樣,觸發(fā)器的邏輯總是越簡(jiǎn)單越好,我們應(yīng)該讓數(shù)據(jù)庫(kù)做它擅長(zhǎng)做的事,不能想著所有邏輯都在數(shù)據(jù)庫(kù)層面實(shí)現(xiàn)。
到此這篇關(guān)于從零開始MySQL觸發(fā)器實(shí)戰(zhàn)攻略的文章就介紹到這了,更多相關(guān)mysql觸發(fā)器內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- MySQL觸發(fā)器Trigger加載及目前局限性
- 一文教你如何使用MySQL觸發(fā)器
- 淺談MySQL觸發(fā)器的原理以及使用
- MySQL存儲(chǔ)函數(shù)以及觸發(fā)器詳解
- MySQL中的觸發(fā)器trigger用法解析
- MySQL如何創(chuàng)建觸發(fā)器(CREATE TRIGGER)
- Mysql觸發(fā)器字段雙向更新方式
- mysql觸發(fā)器中監(jiān)控字段的改變方式
- mysql觸發(fā)器同步表的數(shù)據(jù)方式
- MySQL觸發(fā)器實(shí)現(xiàn)兩表數(shù)據(jù)同步的代碼詳解
- MySQL使用觸發(fā)器實(shí)現(xiàn)數(shù)據(jù)自動(dòng)更新的應(yīng)用實(shí)例
- MySQL 觸發(fā)器(TRIGGER)的具體使用
相關(guān)文章
mysql中使用sql命令將時(shí)間戳解析成datetime類型存入
這篇文章主要介紹了mysql中使用sql命令將時(shí)間戳解析成datetime類型存入,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-11-11MySQL中禁止修改數(shù)據(jù)庫(kù)表特定列的實(shí)現(xiàn)
本文主要介紹了MySQL數(shù)據(jù)庫(kù)中使用觸發(fā)器禁止修改特定列,以保護(hù)數(shù)據(jù)的一致性和完整性,下面就來(lái)介紹一下,感興趣的可以了解一下2024-12-12MySQL錯(cuò)誤提示:sql_mode=only_full_group_by完美解決方案
有時(shí)候遇到數(shù)據(jù)庫(kù)重復(fù)數(shù)據(jù),需要將數(shù)據(jù)進(jìn)行分組,并取出其中一條來(lái)展示,這時(shí)就需要用到group by語(yǔ)句,下面這篇文章主要給大家介紹了關(guān)于MySQL錯(cuò)誤提示:sql_mode=only_full_group_by的完美解決方案,需要的朋友可以參考下2022-10-10MySQL數(shù)據(jù)庫(kù)索引的最左匹配原則
sql查詢用到索引的條件是必須要遵守最左前綴原則,本文就詳細(xì)的介紹了MySQL數(shù)據(jù)庫(kù)索引的最左匹配原則,感興趣的可以了解一下2021-11-11MySQL定時(shí)全庫(kù)備份數(shù)據(jù)庫(kù)
數(shù)據(jù)備份真的很重要, 因?yàn)榭赡苡幸惶鞌?shù)據(jù)會(huì)被莫名其妙的刪掉了,本文主要介紹了MySQL定時(shí)備份數(shù)據(jù)庫(kù),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-07-07十個(gè)節(jié)省時(shí)間的MySQL命令小結(jié)
編者在工作中積累起來(lái)了一些MySQL命令行客戶端技巧,這些技巧或多或少會(huì)幫助您節(jié)省大量的時(shí)間。2011-03-03MySQL 如何查找并刪除重復(fù)記錄的實(shí)現(xiàn)
這篇文章主要介紹了MySQL 如何查找并刪除重復(fù)記錄的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08