mysql觸發(fā)器trigger實例詳解
MySQL好像從5.0.2版本就開始支持觸發(fā)器的功能了,本次博客就來介紹一下觸發(fā)器,首先還是談下概念性的東西吧:
什么是觸發(fā)器觸發(fā)器是與表有關(guān)的數(shù)據(jù)庫對象,在滿足定義條件時觸發(fā),并執(zhí)行觸發(fā)器中定義的語句集合。觸發(fā)器的這種特性可以協(xié)助應(yīng)用在數(shù)據(jù)庫端確保數(shù)據(jù)的完整性。
舉個例子,比如你現(xiàn)在有兩個表【用戶表】和【日志表】,當一個用戶被創(chuàng)建的時候,就需要在日志表中插入創(chuàng)建的log日志,如果在不使用觸發(fā)器的情況下,你需要編寫程序語言邏輯才能實現(xiàn),但是如果你定義了一個觸發(fā)器,觸發(fā)器的作用就是當你在用戶表中插入一條數(shù)據(jù)的之后幫你在日志表中插入一條日志信息。當然觸發(fā)器并不是只能進行插入操作,還能執(zhí)行修改,刪除。
創(chuàng)建觸發(fā)器創(chuàng)建觸發(fā)器的語法如下:
CREATE TRIGGER trigger_name trigger_time trigger_event ON tb_name FOR EACH ROW trigger_stmttrigger_name:觸發(fā)器的名稱tirgger_time:觸發(fā)時機,為BEFORE或者AFTERtrigger_event:觸發(fā)事件,為INSERT、DELETE或者UPDATEtb_name:表示建立觸發(fā)器的表明,就是在哪張表上建立觸發(fā)器trigger_stmt:觸發(fā)器的程序體,可以是一條SQL語句或者是用BEGIN和END包含的多條語句所以可以說MySQL創(chuàng)建以下六種觸發(fā)器:BEFORE INSERT,BEFORE DELETE,BEFORE UPDATEAFTER INSERT,AFTER DELETE,AFTER UPDATE
其中,觸發(fā)器名參數(shù)指要創(chuàng)建的觸發(fā)器的名字
BEFORE和AFTER參數(shù)指定了觸發(fā)執(zhí)行的時間,在事件之前或是之后
FOR EACH ROW表示任何一條記錄上的操作滿足觸發(fā)事件都會觸發(fā)該觸發(fā)器
創(chuàng)建有多個執(zhí)行語句的觸發(fā)器CREATE TRIGGER 觸發(fā)器名 BEFORE|AFTER 觸發(fā)事件ON 表名 FOR EACH ROWBEGIN 執(zhí)行語句列表END
其中,BEGIN與END之間的執(zhí)行語句列表參數(shù)表示需要執(zhí)行的多個語句,不同語句用分號隔開
tips:一般情況下,mysql默認是以 ; 作為結(jié)束執(zhí)行語句,與觸發(fā)器中需要的分行起沖突
為解決此問題可用DELIMITER,如:DELIMITER ||,可以將結(jié)束符號變成||
當觸發(fā)器創(chuàng)建完成后,可以用DELIMITER ;來將結(jié)束符號變成;
mysql> DELIMITER ||mysql> CREATE TRIGGER demo BEFORE DELETE -> ON users FOR EACH ROW -> BEGIN -> INSERT INTO logs VALUES(NOW()); -> INSERT INTO logs VALUES(NOW()); -> END -> ||Query OK, 0 rows affected (0.06 sec)mysql> DELIMITER ;
上面的語句中,開頭將結(jié)束符號定義為||,中間定義一個觸發(fā)器,一旦有滿足條件的刪除操作
就會執(zhí)行BEGIN和END中的語句,接著使用||結(jié)束
最后使用DELIMITER ; 將結(jié)束符號還原
tigger_event:
load data語句是將文件的內(nèi)容插入到表中,相當于是insert語句,而replace語句在一般的情況下和insert差不多,但是如果表中存在primary 或者unique索引的時候,如果插入的數(shù)據(jù)和原來的primary key或者unique相同的時候,會刪除原來的數(shù)據(jù),然后增加一條新的數(shù)據(jù),所以有的時候執(zhí)行一條replace語句相當于執(zhí)行了一條delete和insert語句。
觸發(fā)器可以是一條SQL語句,也可以是多條SQL代碼塊,那如何創(chuàng)建呢?
DELIMITER $ #將語句的分隔符改為$BEGINsql1;sql2;...sqlnEND $DELIMITER ; #將語句的分隔符改回原來的分號';'在BEGIN...END語句中也可以定義變量,但是只能在BEGIN...END內(nèi)部使用:DECLARE var_name var_type [DEFAULT value] #定義變量,可指定默認值SET var_name = value #給變量賦值NEW和OLD的使用:
根據(jù)以上的表格,可以使用一下格式來使用相應(yīng)的數(shù)據(jù):
NEW.columnname:新增行的某列數(shù)據(jù)OLD.columnname:刪除行的某列數(shù)據(jù)說了這么多現(xiàn)在我們來創(chuàng)建一個觸發(fā)器吧!現(xiàn)在有表如下:
用戶users表
CREATE TABLE `users` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `name` varchar(255) CHARACTER SET utf8mb4 DEFAULT NULL, `add_time` int(11) DEFAULT NULL, PRIMARY KEY (`id`), KEY `name` (`name`(250)) USING BTREE) ENGINE=MyISAM AUTO_INCREMENT=1000001 DEFAULT CHARSET=latin1;
日志logs表:
CREATE TABLE `logs` ( `Id` int(11) NOT NULL AUTO_INCREMENT, `log` varchar(255) DEFAULT NULL COMMENT ’日志說明’, PRIMARY KEY (`Id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT=’日志表’;
需求是:當在users中插入一條數(shù)據(jù),就會在logs中生成一條日志信息。
創(chuàng)建觸發(fā)器:
DELIMITER $CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROWBEGINDECLARE s1 VARCHAR(40)character set utf8;DECLARE s2 VARCHAR(20) character set utf8;#后面發(fā)現(xiàn)中文字符編碼出現(xiàn)亂碼,這里設(shè)置字符集SET s2 = ' is created';SET s1 = CONCAT(NEW.name,s2); #函數(shù)CONCAT可以將字符串連接INSERT INTO logs(log) values(s1);END $DELIMITER ;
這里我用的navicat:
查看觸發(fā)器SHOW TRIGGERS語句查看觸發(fā)器信息
Tip:
上面我用的navicat直接創(chuàng)建,如果大家用的mysql front,name這里會有個區(qū)別,我們刪除剛才的觸發(fā)器,在Mysql front中測試
drop trigger user_log;#刪除觸發(fā)器
打開Mysql Front:
mysql front在編譯sql時,不用定義結(jié)尾分隔符,修改后的sql直接這樣既可:
#DELIMITER $CREATE TRIGGER user_log AFTER INSERT ON users FOR EACH ROWBEGINDECLARE s1 VARCHAR(40)character set utf8;DECLARE s2 VARCHAR(20) character set utf8;SET s2 = ' is created';SET s1 = CONCAT(NEW.name,s2); #函數(shù)CONCAT可以將字符串連接INSERT INTO logs(log) values(s1);END #$#DELIMITER ;
這里再??錄婦洌?/p>
tips:SHOW TRIGGERS語句無法查詢指定的觸發(fā)器
在triggers表中查看觸發(fā)器信息
SELECT * FROM information_schema.triggers;
結(jié)果顯示了所有觸發(fā)器的詳細信息,同時,該方法可以查詢制定觸發(fā)器的詳細信息
SELECT * FROM information_schema.triggers WHERE TRIGGER_NAME=’user_log’;
tips:所有觸發(fā)器信息都存儲在information_schema數(shù)據(jù)庫下的triggers表中
可以使用SELECT語句查詢,如果觸發(fā)器信息過多,最好通過TRIGGER_NAME字段指定查詢
回到上面,我們創(chuàng)建好了觸發(fā)器,繼續(xù)在users中插入數(shù)據(jù)并查看數(shù)據(jù):
insert into users(name,add_time) values(’周伯通’,now());
好吧,我們再來查看一下logs表吧!
通過上面的例子,可以看到只需要在users中插入用戶的信息,日志會自動記錄到logs表中,這也許就是觸發(fā)器給我?guī)淼谋憬莅桑?
限制和注意事項觸發(fā)器會有以下兩種限制:
1.觸發(fā)程序不能調(diào)用將數(shù)據(jù)返回客戶端的存儲程序,也不能使用采用CALL語句的動態(tài)SQL語句,但是允許存儲程序通過參數(shù)將數(shù)據(jù)返回觸發(fā)程序,也就是存儲過程或者函數(shù)通過OUT或者INOUT類型的參數(shù)將數(shù)據(jù)返回觸發(fā)器是可以的,但是不能調(diào)用直接返回數(shù)據(jù)的過程。
2.不能再觸發(fā)器中使用以顯示或隱式方式開始或結(jié)束事務(wù)的語句,如START TRANS-ACTION,COMMIT或ROLLBACK。
注意事項:MySQL的觸發(fā)器是按照BEFORE觸發(fā)器、行操作、AFTER觸發(fā)器的順序執(zhí)行的,其中任何一步發(fā)生錯誤都不會繼續(xù)執(zhí)行剩下的操作,如果對事務(wù)表進行的操作,如果出現(xiàn)錯誤,那么將會被回滾,如果是對非事務(wù)表進行操作,那么就無法回滾了,數(shù)據(jù)可能會出錯。
總結(jié)觸發(fā)器是基于行觸發(fā)的,所以刪除、新增或者修改操作可能都會激活觸發(fā)器,所以不要編寫過于復(fù)雜的觸發(fā)器,也不要增加過得的觸發(fā)器,這樣會對數(shù)據(jù)的插入、修改或者刪除帶來比較嚴重的影響,同時也會帶來可移植性差的后果,所以在設(shè)計觸發(fā)器的時候一定要有所考慮。
觸發(fā)器是一種特殊的存儲過程,它在插入,刪除或修改特定表中的數(shù)據(jù)時觸發(fā)執(zhí)行,它比數(shù)據(jù)庫本身標準的功能有更精細和更復(fù)雜的數(shù)據(jù)控制能力。
數(shù)據(jù)庫觸發(fā)器有以下的作用:
1.安全性。可以基于數(shù)據(jù)庫的值使用戶具有操作數(shù)據(jù)庫的某種權(quán)利。
# 可以基于時間限制用戶的操作,例如不允許下班后和節(jié)假日修改數(shù)據(jù)庫數(shù)據(jù)。
# 可以基于數(shù)據(jù)庫中的數(shù)據(jù)限制用戶的操作,例如不允許股票的價格的升幅一次超過10%。
2.審計。可以跟蹤用戶對數(shù)據(jù)庫的操作。
# 審計用戶操作數(shù)據(jù)庫的語句。
# 把用戶對數(shù)據(jù)庫的更新寫入審計表。
3.實現(xiàn)復(fù)雜的數(shù)據(jù)完整性規(guī)則
# 實現(xiàn)非標準的數(shù)據(jù)完整性檢查和約束。觸發(fā)器可產(chǎn)生比規(guī)則更為復(fù)雜的限制。與規(guī)則不同,觸發(fā)器可以引用列或數(shù)據(jù)庫對象。例如,觸發(fā)器可回退任何企圖吃進超過自己保證金的期貨。
# 提供可變的缺省值。
4.實現(xiàn)復(fù)雜的非標準的數(shù)據(jù)庫相關(guān)完整性規(guī)則。觸發(fā)器可以對數(shù)據(jù)庫中相關(guān)的表進行連環(huán)更新。例如,在auths表author_code列上的刪除觸發(fā)器可導(dǎo)致相應(yīng)刪除在其它表中的與之匹配的行。
# 在修改或刪除時級聯(lián)修改或刪除其它表中的與之匹配的行。
# 在修改或刪除時把其它表中的與之匹配的行設(shè)成NULL值。
# 在修改或刪除時把其它表中的與之匹配的行級聯(lián)設(shè)成缺省值。
# 觸發(fā)器能夠拒絕或回退那些破壞相關(guān)完整性的變化,取消試圖進行數(shù)據(jù)更新的事務(wù)。當插入一個與其主健不匹配的外部鍵時,這種觸發(fā)器會起作用。例如,可以在books.author_code 列上生成一個插入觸發(fā)器,如果新值與auths.author_code列中的某值不匹配時,插入被回退。
5.同步實時地復(fù)制表中的數(shù)據(jù)。
6.自動計算數(shù)據(jù)值,如果數(shù)據(jù)的值達到了一定的要求,則進行特定的處理。例如,如果公司的帳號上的資金低于5萬元則立即給財務(wù)人員發(fā)送警告數(shù)據(jù)。
到此這篇關(guān)于mysql觸發(fā)器trigger實例詳解的文章就介紹到這了,更多相關(guān)mysql觸發(fā)器實例內(nèi)容請搜索好吧啦網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持好吧啦網(wǎng)!
相關(guān)文章:
1. Oracle數(shù)據(jù)庫備份與恢復(fù)精華資料集錦2. Oracle數(shù)據(jù)庫不完全恢復(fù)實例3. 怎樣才能保護好SQL Server 數(shù)據(jù)庫4. MySQL case when使用方法實例解析5. 解讀Oracle數(shù)據(jù)庫后臺進程的功能6. MySQL索引背后的數(shù)據(jù)結(jié)構(gòu)及算法原理7. MySql分頁時使用limit+order by會出現(xiàn)數(shù)據(jù)重復(fù)問題解決8. Sql Server 壓縮數(shù)據(jù)庫日志文件的方法9. MySQL 性能、監(jiān)控與災(zāi)難恢復(fù)10. 實例講解SQL Server中非常有用EXISTS結(jié)構(gòu)
