? ? ?觸發(fā)器是一種特殊類型的存儲過程,它不同于之前的我們介紹的存儲過程。觸發(fā)器主要是通過事件進行觸發(fā)被自動調(diào)用執(zhí)行的。而存儲過程可以通過存儲過程的名稱被調(diào)用。?
??????觸發(fā)器的主要作用就是能夠?qū)崿F(xiàn)比參照完整性更為復(fù)雜的兩張表或多張表之間的數(shù)據(jù)的完整性和一致性,從而保證表中的數(shù)據(jù)的變化符合數(shù)據(jù)庫設(shè)計者確定的業(yè)務(wù)規(guī)則。?
??????觸發(fā)器對表進行插入、更新、刪除的時候會自動執(zhí)行的特殊存儲過程。觸發(fā)器一般用在check約束更加復(fù)雜的約束上面。?
??????觸發(fā)器和普通的存儲過程的區(qū)別是:觸發(fā)器是當(dāng)對某一個表進行操作。諸如:update、insert、delete這些操作的時候,系統(tǒng)會自動調(diào)用執(zhí)行該表上對應(yīng)的觸發(fā)器。?
??????sql server 2005中觸發(fā)器可以分為兩類:dml觸發(fā)器和ddl觸發(fā)器,其中ddl觸發(fā)器它們會影響多種數(shù)據(jù)定義語言語句而激發(fā),這些語句有create、alter、drop語句。
DML觸發(fā)器分為:
1、 after觸發(fā)器(之后觸發(fā))?
??????a、 insert觸發(fā)器?
??????b、 update觸發(fā)器?
??????c、 delete觸發(fā)器?
2、 instead of 觸發(fā)器 (之前觸發(fā))?
3、區(qū)別?
??????after觸發(fā)器:要求只有執(zhí)行某一操作insert、update、delete之后觸發(fā)器才被觸發(fā),且只能定義在表上。?
??????instead of觸發(fā)器:表示并不執(zhí)行其定義的操作(insert、update、delete)而僅是執(zhí)行觸發(fā)器本身。既可以在表上定義instead of觸發(fā)器,也可以在視圖上定義。
inserted 表和 deleted 表
? ?在使用觸發(fā)器時,SQL Server會為每個觸發(fā)器建立兩個特殊的臨時表,即inserted表和deleted表。這兩個表存儲在內(nèi)存中,與創(chuàng)建觸發(fā)器的表具有相同的結(jié)構(gòu),由系統(tǒng)維護和管理,不允許用戶對其進行修改。每個觸發(fā)器只能訪問自己的臨時表,觸發(fā)器執(zhí)行完畢以后,兩表會自動釋放。?
??????(1)inserted表用于存儲insert或update語句所影響的行的副本。當(dāng)執(zhí)行insert或update操作時,新的數(shù)據(jù)行同時被添加到激活觸發(fā)器的基本表和inserted表中。?
??????(2)deleted表用于存儲delete或update語句所影響的行的副本。當(dāng)執(zhí)行delete或update操作時,指定的原數(shù)據(jù)行被從基本表中刪除,然后被轉(zhuǎn)移到deleted表中。一般來說,在基本表和deleted表中不會存在相同的數(shù)據(jù)行。?
?????? 說明:?
??????update操作分為兩步:首先將基本表中修改的原數(shù)據(jù)行轉(zhuǎn)移到deleted表中,然后從inserted表中復(fù)制修改后的新數(shù)據(jù)行到基本表中。也就是說,對于update操作,deleted表中存放的是修改之前的舊值,inserted表中存放的是修改之后的新值。
觸發(fā)器創(chuàng)建語法四要素:
1.監(jiān)視地點(table)? 2.監(jiān)視事件(insert/update/delete)? 3.觸發(fā)時間(after/before)? 4.觸發(fā)事件(insert/update/delete)
語法:
delimiter?&&create?trigger?trigger Nameafter/before?insert/update/delete?on?表名 for?each?row???#這句話在mysql是固定的 beginsql語句; end&&
商品表
mysql>?create?table?g( ????->?id?int?auto_increment?primary?key,????->?name?varchar(10),????->?num?int????->?);
訂單表
mysql>?create?table?o( ????->?idd?int?auto_increment?primary?key,????->?gid?int,????->?much?int????->?);
插入商品:
mysql>?insert?into?g?(name,num)?value?('juzi',20);mysql>?select?*?from?g; +----+------+------+|?id?|?name?|?num??| +----+------+------+|??3?|?juzi?|???20?| +----+------+------+
如果我們在沒使用觸發(fā)器之前:假設(shè)我們現(xiàn)在賣了3個商品1,我們需要做兩件事
1.往訂單表插入一條記錄
insert?into?o(gid,much)?values(1,3);
2.更新商品表商品1的剩余數(shù)量
update?g?set?num=num-3?where?id=1;
創(chuàng)建觸發(fā)器:
delimiter?& mysql>?create?trigger?trg1 ????->?after?insert?on?o????->?for?each?row????->?begin????->?update?g?set?num?=?num?-3?where?id?=?1;????->?end&
執(zhí)行:
insert?into?o(gid,much)?values(1,3)$
結(jié)果:
會發(fā)現(xiàn)商品1的數(shù)量變?yōu)?了,說明在我們插入一條訂單的時候,觸發(fā)器自動幫我們做了更新操作。
但現(xiàn)在會有一個問題,因為我們觸發(fā)器里面num和id都是寫死的,所以不管我們買哪個商品,最終更新的都是商品1的數(shù)量。比如:我們往訂單表再插入一條記錄:insert into o(gid,much) values(2,3),執(zhí)行完后會發(fā)現(xiàn)商品1的數(shù)量變4了,而商品2的數(shù)量沒變,這樣顯然不是我們想要的結(jié)果。我們需要改改我們之前創(chuàng)建的觸發(fā)器。
我們?nèi)绾卧谟|發(fā)器引用行的值,也就是說我們要得到我們新插入的訂單記錄中的gid或much的值。
對于insert而言,新插入的行用new來表示,行中的每一列的值用new.列名來表示。
所以現(xiàn)在我們可以這樣來改我們的觸發(fā)器
create?trigger?tg2? after?insert?on?o? for?each?row? begin? update?g?set?num=num-new.much?where?id=new.gid;(注意此處和第一個觸發(fā)器的不同)? end$
第二個觸發(fā)器創(chuàng)建完畢,我們先把第一個觸發(fā)器刪掉
drop trigger tg1$
再來測試一下,插入一條訂單記錄:insert into o(gid,much) values(2,3)$
執(zhí)行完發(fā)現(xiàn)商品2的數(shù)量變?yōu)?了,現(xiàn)在就對了。
現(xiàn)在還存在兩種情況:
1.當(dāng)用戶撤銷一個訂單的時候,我們這邊直接刪除一個訂單,我們是不是需要把對應(yīng)的商品數(shù)量再加回去呢?
2.當(dāng)用戶修改一個訂單的數(shù)量時,我們觸發(fā)器修改怎么寫?
我們先分析一下第一種情況:
監(jiān)視地點:o表
監(jiān)視事件:delete
觸發(fā)時間:after
觸發(fā)事件:update
對于delete而言:原本有一行,后來被刪除,想引用被刪除的這一行,用old來表示,old.列名可以引用被刪除的行的值。
那我們的觸發(fā)器就該這樣寫:
create?trigger?tg3 after?delete?on?o for?each?row begin update?g?set?num?=?num?+?old.much?where?id?=?old.gid;(注意這邊的變化) end$
創(chuàng)建完畢。
再執(zhí)行
delete?from?o?where?oid?=?2$
會發(fā)現(xiàn)商品2的數(shù)量又變?yōu)?0了。
第二種情況:
監(jiān)視地點:o表
監(jiān)視事件:update
觸發(fā)時間:after
觸發(fā)事件:update
對于update而言:被修改的行,修改前的數(shù)據(jù),用old來表示,old.列名引用被修改之前行中的值;
修改的后的數(shù)據(jù),用new來表示,new.列名引用被修改之后行中的值。
那我們的觸發(fā)器就該這樣寫:
create?trigger?tg4 after?update?on?o for?each?row begin update?g?set?num?=?num+old.much-new.much?where?id?=?old/new.gid; end$
先把舊的數(shù)量恢復(fù)再減去新的數(shù)量就是修改后的數(shù)量了。
我們來測試下:先把商品表和訂單表的數(shù)據(jù)都清掉,易于測試。
假設(shè)我們往商品表插入三個商品,數(shù)量都是10,
買3個商品1:
insert?into?o(gid,much)?values(1,3)$
這時候商品1的數(shù)量變?yōu)?;
我們再修改插入的訂單記錄:
update?o?set?much?=?5?where?oid?=?1$
我們變?yōu)橘I5個商品1,這時候再查詢商品表就會發(fā)現(xiàn)商品1的數(shù)量只剩5了,說明我們的觸發(fā)器發(fā)揮作用了。
以上就是?【MySQL 12】觸發(fā)器的內(nèi)容,更多相關(guān)內(nèi)容請關(guān)注PHP中文網(wǎng)(www.php.cn)!