內容源自:一篇很棒的 MySQL 觸發器學習教程mysql
觸發器(trigger):監視某種狀況,並觸發某種操做,它是提供給程序員和數據分析員來保證數據完整性的一種方法,它是與表事件相關的特殊的存儲過程,它的執行不是由程序調用,也不是手工啓動,而是由事件來觸發,例如當對一個表進行操做( insert,delete, update)時就會激活它執行。
觸發器常常用於增強數據的完整性約束和業務規則等。 觸發器建立語法四要素:
1.監視地點(table)
2.監視事件(insert/update/delete)
3.觸發時間(after/before)
4.觸發事件(insert/update/delete)
觸發器基本語法以下所示:程序員
其中:trigger_time是觸發器的觸發事件,能夠爲before(在檢查約束前觸發)或after(在檢查約束後觸發);trigger_event是觸發器的觸發事件,包括insert、update和delete,需注意對同一個表相同觸發時間的相同觸發事件,只能定義一個觸發器;可使用old和new來引用觸發器中發生變化的記錄內容。
觸發器SQL語法:sql
create trigger triggerName
after/before insert/update/delete on 表名
for each row #這句話在mysql是固定的
begin
sql語句;
end;數據庫
假設存在一張學生表(student),包括學生的基本信息,學號(stuid)爲主鍵。segmentfault
另外存在一張成績表(cj),對應每一個學生包括一個值。其中number表示序號爲主鍵,自動遞增序列。它在插入過程當中默認自增。同時假設成績表中包括學生姓名和學號。後端
該成績表目前沒有值,先須要設計一個觸發器,當增長新的學生時,須要在成績表中插入對應的學生信息,至於具體math、chinese、english後面由老師打分更新便可。
那麼,如何設計觸發器呢?
1.首先它是一個插入Insert觸發器,是創建在表student上的;
2.而後是after,插入後的事件;
3.事件內容是插入成績表,主須要插入學生的學號和姓名,number爲自增,而成績目前不須要。
注意:new表示student中新插入的值。服務器
create trigger ins_stu
after insert on student for each row
begin
insert into cj ( stu_id, stu_name)
values( new.stuid, new.username);
end;網絡
而後插入數據:
insert student values ('eastmount','111111','6','1991-12-05');
同時插入兩個數據,觸發器正確執行了~ 架構
注意:建立觸發器和表同樣,建議增長判斷:DROP TRIGGER IF EXISTS `ins_stu`;併發
這裏簡單講述幾個判斷插入類型的觸發器。
好比觸發器調用,當插入時間小時爲20時,對數據進行插入:
DROP TRIGGER IF EXISTS `ins_info`;
create trigger ins_info
after insert on nhfxelect for each row
begin
if HOUR(new.RecordTime)='20' then
insert into nhfxbyhour (UnitDepName, UnitDepCode, ElectCost, TimeJG, RecordTime)
values( '數統學院', '1', new.USERKWH, '20', new.RecordTime);
end if;
end;
這個觸發器中,RecordTime爲datetime類型,如"2016-08-28 20:10:00",這時hour()這個值爲20才能插入;不然數據不能插入。同時能夠date_format(new.RecordTime, '%Y-%m-%d')判斷日期爲某天或某年某月進行插入。
同時,再如更新觸發器,若是設置的值爲某個範圍,才進行操做或性別爲"男"或"女"才進行操做。
基本語法:
if 判斷條件 then
sql語句;
end if;
假設存在一個實時插入數據的服務器,例如學生的消費金額或用電量等。
StuCost:學生的用電數據,實時插入,Cost爲每30秒消費金額,RecordTime爲每分鐘插入時間,datetime類型;
StuCostbyHour:統計學生一小時的消費金額,HourCost爲金額總數,按小時統計,TimeJD時間段,1~24,對應每小時,RecordTime爲統計時間。
如今須要設計一個實時更新觸發器,當插入消費數據時,按小時統計學生的消費金額,同理,用電量等。
DROP TRIGGER IF EXISTS `upd_info`;
create trigger upd_info
after insert on StuCost for each row
begin
update StuCostbyHour set HourCost = HourCost + new.Cost
where (TimeJD = hour(new.RecordTime) + 1) and date_format(new.RecordTime, '%Y-%m-%d') = date_format(RecordTime, '%Y-%m-%d');
end;
SQL語句中,須要獲取插入的時間,而後經過TimeJD時間段和日期RecordTime找到對應的值,而後進行累加便可。以下圖所示:
問題一:
大型系統必須得要存儲過程和觸發器嗎? - 知乎
回答1:
咱們先要弄清楚二個問題:
1.什麼是大型系統?
2.你討論的是什麼領域的應用,能夠大體分爲二種:互聯網、企業內部
接下來給你舉一些例子:
1.SAP、peopleSoft、ERP等企業級別應用
通常狀況下,會使用存儲過程和觸發器,減小開發成本,畢竟其業務邏輯修改頻繁,並且爲通用,不少時候會把一些業務邏輯編寫成存儲過程,像Oracle會寫成包,比存儲過程更強大。
另一個緣由是服務器的負載是可控,也即系統的訪問人數首先是可控的,沒有那麼大,並且這些數據又很是關鍵,爲此每每使用的設備也比較好,多用存儲櫃子支撐數據庫。
2.另一類互聯網行業的
好比淘寶、知呼、微博等,數據庫的壓力是很是大的,也每每會最容易成爲瓶頸,並且多用PC服務器支撐,用戶量的增速是不可控的,同時在線訪問的用戶量也是不可控的,爲此確定會把業務邏輯放到其餘語言的代碼層,並且能夠藉助一些LVS等類型軟硬件作負載均衡,以及平滑增減Web層的服務器,從而達到線性的增減而支持大規模的訪問。
因此無論你的這個系統是否龐大,首先要分業務支持的對象,系統最可能容易出現瓶頸的地方在那?
固然也不是說互聯網行業的應用就絕對不用存儲過程,這個也不對,曾在阿里作的Oracle遷移MySQL系統確實用了,由於歷史的緣由,另外還有一些新系統也有用,好比晚上進行按期的數據統計的一些操做,不過有量上的控制。存儲過程是好東西,要分場景,分業務類型來用就能夠把握好。
回答2:
確定不能一刀切的說能用或者不能用,不一樣類型的系統、不一樣的規模、不一樣的歷史緣由都會有不一樣的解決方案。
通常狀況下,Web應用的瓶頸常在DB上,因此會盡量的減小DB作的事情,把耗時的服務作成Scale Out,這種狀況下,確定不會使用存儲過程;而若是隻是通常的應用,DB沒有性能上的問題,在適當的場景下,也可使用存儲過程。
至於觸發器,我是知道有這東西但歷來沒用過。我但願風險可控,遇到問題可以快速的找到緣由,儘量不會去使用觸發器。
回答3:
1.PLSQL能夠大大下降parse/exec 百分比;
2.存儲過程能夠自動完成靜態SQL variable bind;
3.存儲過程大大減小了JDBC網絡傳輸與交互,速度快;
4.oracle 中存儲過程內部commit爲異步寫,必定程度上減小了等redo日誌落地時間;
5.存儲過程最大問題就是給數據庫開發工做壓力太大,另外架構升級時候會比較難解耦;
6.觸發器不推薦使用,觸發操做能在業務層解決就在業務層解決,不然很難維護,並且容易產生死鎖。
問題2:
爲何你們都不推薦使用MySQL觸發器而用存儲過程?- segmentfault
回答1:
1.存儲過程和觸發器兩者是有很大的聯繫的,個人通常理解就是觸發器是一個隱藏的存儲過程,由於它不須要參數,不須要顯示調用,每每在你不知情的狀況下已經作了不少操做。從這個角度來講,因爲是隱藏的,無形中增長了系統的複雜性,非DBA人員理解起來數據庫就會有困難,由於它不執行根本感受不到它的存在。
2.再有,涉及到複雜的邏輯的時候,觸發器的嵌套是避免不了的,若是再涉及幾個存儲過程,再加上事務等等,很容易出現死鎖現象,再調試的時候也會常常性的從一個觸發器轉到另一個,級聯關係的不斷追溯,很容易令人頭大。其實,從性能上,觸發器並無提高多少性能,只是從代碼上來講,可能在coding的時候很容易實現業務,因此個人觀點是:摒棄觸發器!觸發器的功能基本均可以用存儲過程來實現。
3.在編碼中存儲過程顯示調用很容易閱讀代碼,觸發器隱式調用容易被忽略。
4.存儲過程的致命傷在於移植性,存儲過程不能跨庫移植,好比事先是在mysql數據庫的存儲過程,考慮性能要移植到oracle上面那麼全部的存儲過程都須要被重寫一遍。
回答2:
這種東西只有在併發不高的項目,管理系統中用。若是是面向用戶的高併發應用,都不要使用。
觸發器和存儲過程自己難以開發和維護,不能高效移植。觸發器徹底能夠用事務替代。存儲過程能夠用後端腳本替代。
回答3:
我以爲來自兩方面的因素:
1.存儲過程須要顯式調用,意思是閱讀源碼的時候你能知道存儲過程的存在,而觸發器必須在數據庫端才能看到,容易被忽略。
2.Mysql的觸發器自己不是很好,好比after delete沒法鏈式反應的問題。
我認爲性能上其實仍是觸發器佔優點的,可是基於以上緣由不受青睞。
最後但願這篇文章對你有所幫助,尤爲是學習MySQL觸發器的同窗,你能夠經過觸發器實現一些功能,同時須要注意合理的使用觸發器,但這個過程須要你不斷的去積累和開發,才能真正理解它的用法和使用場所。