mysql好像從5.0.2版本就開始支持觸發器的功能了,本次博客就來介紹一下觸發器,首先還是談下概念性的東西吧:
什么是觸發器
觸發器是與表有關的數據庫對象,在滿足定義條件時觸發,并執行觸發器中定義的語句集合。觸發器的這種特性可以協助應用在數據庫端確保數據的完整性。
舉個例子,比如你現在有兩個表【用戶表】和【日志表】,當一個用戶被創建的時候,就需要在日志表中插入創建的log日志,如果在不使用觸發器的情況下,你需要編寫程序語言邏輯才能實現,但是如果你定義了一個觸發器,觸發器的作用就是當你在用戶表中插入一條數據的之后幫你在日志表中插入一條日志信息。當然觸發器并不是只能進行插入操作,還能執行修改,刪除。
創建觸發器
創建觸發器的語法如下:
1
2
3
4
5
6
7
8
9
|
create trigger trigger_name trigger_time trigger_event on tb_name for each row trigger_stmt trigger_name:觸發器的名稱 tirgger_time:觸發時機,為before或者 after trigger_event:觸發事件,為 insert 、 delete 或者 update tb_name:表示建立觸發器的表明,就是在哪張表上建立觸發器 trigger_stmt:觸發器的程序體,可以是一條sql語句或者是用 begin 和 end 包含的多條語句 所以可以說mysql創建以下六種觸發器: before insert ,before delete ,before update after insert , after delete , after update |
其中,觸發器名參數指要創建的觸發器的名字
before
和after
參數指定了觸發執行的時間,在事件之前或是之后
for each row
表示任何一條記錄上的操作滿足觸發事件都會觸發該觸發器
創建有多個執行語句的觸發器
1
2
3
4
5
|
create trigger 觸發器名 before| after 觸發事件 on 表名 for each row begin 執行語句列表 end |
其中,begin與end之間的執行語句列表參數表示需要執行的多個語句,不同語句用分號隔開
tips:
一般情況下,mysql默認是以 ; 作為結束執行語句,與觸發器中需要的分行起沖突
為解決此問題可用delimiter,如:delimiter ||,可以將結束符號變成||
當觸發器創建完成后,可以用delimiter ;來將結束符號變成;
1
2
3
4
5
6
7
8
9
10
11
|
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 ; |
上面的語句中,開頭將結束符號定義為||,中間定義一個觸發器,一旦有滿足條件的刪除操作
就會執行begin和end中的語句,接著使用||結束
最后使用delimiter ; 將結束符號還原
tigger_event:
load data語句是將文件的內容插入到表中,相當于是insert語句,而replace語句在一般的情況下和insert差不多,但是如果表中存在primary 或者unique索引的時候,如果插入的數據和原來的primary key或者unique相同的時候,會刪除原來的數據,然后增加一條新的數據,所以有的時候執行一條replace語句相當于執行了一條delete和insert語句。
觸發器可以是一條sql語句,也可以是多條sql代碼塊,那如何創建呢?
1
2
3
4
5
6
7
8
|
delimiter $ #將語句的分隔符改為$ begin sql1; sql2; ... sqln end $ delimiter ; #將語句的分隔符改回原來的分號 ";" |
在begin...end語句中也可以定義變量,但是只能在begin...end內部使用:
1
2
|
declare var_name var_type [ default value] #定義變量,可指定默認值 set var_name = value #給變量賦值 |
new和old的使用:
根據以上的表格,可以使用一下格式來使用相應的數據:
1
2
|
new.columnname:新增行的某列數據 old.columnname:刪除行的某列數據 |
說了這么多現在我們來創建一個觸發器吧!
現在有表如下:
用戶users表
1
2
3
4
5
6
7
|
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表:
1
2
3
4
5
|
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中插入一條數據,就會在logs中生成一條日志信息。
創建觸發器:
1
2
3
4
5
6
7
8
9
10
|
delimiter $ create trigger user_log after insert on users for each row begin declare s1 varchar (40) character set utf8; declare s2 varchar (20) character set utf8;#后面發現中文字符編碼出現亂碼,這里設置字符集 set s2 = " is created" ; set s1 = concat(new. name ,s2); #函數concat可以將字符串連接 insert into logs(log) values (s1); end $ delimiter ; |
這里我用的navicat:
查看觸發器
show triggers語句查看觸發器信息
tip:
1
|
上面我用的navicat直接創建,如果大家用的mysql front, name 這里會有個區別,我們刪除剛才的觸發器,在mysql front中測試 |
1
|
drop trigger user_log;#刪除觸發器 |
打開mysql front:
mysql front在編譯sql時,不用定義結尾分隔符,修改后的sql直接這樣既可:
1
2
3
4
5
6
7
8
9
10
|
#delimiter $ create trigger user_log after insert on users for each row begin declare s1 varchar (40) character set utf8; declare s2 varchar (20) character set utf8; set s2 = " is created" ; set s1 = concat(new. name ,s2); #函數concat可以將字符串連接 insert into logs(log) values (s1); end #$ #delimiter ; |
這里再啰嗦幾句:
tips:show triggers
語句無法查詢指定的觸發器
在triggers表中查看觸發器信息
1
|
select * from information_schema.triggers; |
結果顯示了所有觸發器的詳細信息,同時,該方法可以查詢制定觸發器的詳細信息
1
|
select * from information_schema.triggers where trigger_name= 'user_log' ; |
tips:
所有觸發器信息都存儲在information_schema數據庫下的triggers表中
可以使用select語句查詢,如果觸發器信息過多,最好通過trigger_name字段指定查詢
回到上面,我們創建好了觸發器,繼續在users中插入數據并查看數據:
1
|
insert into users( name ,add_time) values ( '周伯通' ,now()); |
好吧,我們再來查看一下logs表吧!
通過上面的例子,可以看到只需要在users中插入用戶的信息,日志會自動記錄到logs表中,這也許就是觸發器給我帶來的便捷吧!
限制和注意事項
觸發器會有以下兩種限制:
1.觸發程序不能調用將數據返回客戶端的存儲程序,也不能使用采用call語句的動態sql語句,但是允許存儲程序通過參數將數據返回觸發程序,也就是存儲過程或者函數通過out或者inout類型的參數將數據返回觸發器是可以的,但是不能調用直接返回數據的過程。
2.不能再觸發器中使用以顯示或隱式方式開始或結束事務的語句,如start trans-action,commit或rollback。
注意事項:mysql的觸發器是按照before觸發器、行操作、after觸發器的順序執行的,其中任何一步發生錯誤都不會繼續執行剩下的操作,如果對事務表進行的操作,如果出現錯誤,那么將會被回滾,如果是對非事務表進行操作,那么就無法回滾了,數據可能會出錯。
總結
觸發器是基于行觸發的,所以刪除、新增或者修改操作可能都會激活觸發器,所以不要編寫過于復雜的觸發器,也不要增加過得的觸發器,這樣會對數據的插入、修改或者刪除帶來比較嚴重的影響,同時也會帶來可移植性差的后果,所以在設計觸發器的時候一定要有所考慮。
觸發器是一種特殊的存儲過程,它在插入,刪除或修改特定表中的數據時觸發執行,它比數據庫本身標準的功能有更精細和更復雜的數據控制能力。
數據庫觸發器有以下的作用:
1.安全性??梢曰跀祿斓闹凳褂脩艟哂胁僮鲾祿斓哪撤N權利。
# 可以基于時間限制用戶的操作,例如不允許下班后和節假日修改數據庫數據。
# 可以基于數據庫中的數據限制用戶的操作,例如不允許股票的價格的升幅一次超過10%。
2.審計??梢愿櫽脩魧祿斓牟僮鳌?/strong>
# 審計用戶操作數據庫的語句。
# 把用戶對數據庫的更新寫入審計表。
3.實現復雜的數據完整性規則
# 實現非標準的數據完整性檢查和約束。觸發器可產生比規則更為復雜的限制。與規則不同,觸發器可以引用列或數據庫對象。例如,觸發器可回退任何企圖吃進超過自己保證金的期貨。
# 提供可變的缺省值。
4.實現復雜的非標準的數據庫相關完整性規則。觸發器可以對數據庫中相關的表進行連環更新。例如,在auths表author_code列上的刪除觸發器可導致相應刪除在其它表中的與之匹配的行。
# 在修改或刪除時級聯修改或刪除其它表中的與之匹配的行。
# 在修改或刪除時把其它表中的與之匹配的行設成null值。
# 在修改或刪除時把其它表中的與之匹配的行級聯設成缺省值。
# 觸發器能夠拒絕或回退那些破壞相關完整性的變化,取消試圖進行數據更新的事務。當插入一個與其主健不匹配的外部鍵時,這種觸發器會起作用。例如,可以在books.author_code列上生成一個插入觸發器,如果新值與auths.author_code列中的某值不匹配時,插入被回退。
5.同步實時地復制表中的數據。
6.自動計算數據值,如果數據的值達到了一定的要求,則進行特定的處理。例如,如果公司的帳號上的資金低于5萬元則立即給財務人員發送警告數據。
無論從事什么行業,只要做好兩件事就夠了,一個是你的專業、一個是你的人品,專業決定了你的存在,人品決定了你的人脈,剩下的就是堅持,用善良專業和真誠贏取更多的信任。
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關注服務器之家的更多內容!
原文鏈接:https://www.cnblogs.com/phpper/p/7587031.html