李虎軍
摘要:該文介紹了觸發(fā)器類型、特點以及觸發(fā)器產(chǎn)生的兩個臨時表,并著重對觸發(fā)器提高數(shù)據(jù)完整性的應用及其注意事項進行了闡述,以期對數(shù)據(jù)庫設(shè)計者在設(shè)計數(shù)據(jù)庫系統(tǒng)時提高數(shù)據(jù)完整性控制提供有益幫助。
關(guān)鍵詞:完整性;觸發(fā)器;CHECK約束
中圖分類號:TP311 文獻標識碼:A 文章編號:1009-3044(2016)16-0013-02
信息系統(tǒng)開發(fā)與運行離不開數(shù)據(jù)庫系統(tǒng)的支持,而對于數(shù)據(jù)庫而言,其存儲的數(shù)據(jù)的正確性至關(guān)重要。為確保數(shù)據(jù)的正確性,各種DBMS都提供了各種方法或機制進行檢測、檢查。靈活、合理地應用觸發(fā)器對提高信息系統(tǒng)的數(shù)據(jù)正確性有很好的幫助。
1 SQL Server觸發(fā)器
SQL Server觸發(fā)器是一類特殊存儲過程,其由用戶定義在數(shù)據(jù)表上并被事件驅(qū)動的由DBMS調(diào)用執(zhí)行的。觸發(fā)器不能被用戶直接調(diào)用執(zhí)行,也不能接收參數(shù)。在數(shù)據(jù)表上或在數(shù)據(jù)庫對象上定義了相應的觸發(fā)器后,當在數(shù)據(jù)表中DELETE、INSERT、UPDATE操作或在CREATE、DROP、ALTER數(shù)據(jù)庫對象時將激發(fā)并自動執(zhí)行相應的觸發(fā)器,使得相應的操作必須滿足由觸發(fā)器所定義的約束規(guī)則才能得到成功執(zhí)行。引起觸發(fā)器被執(zhí)行的相應操作和觸發(fā)器被統(tǒng)一當作一次事務處理。當事務未能整體成功執(zhí)行,則DBMS會自動回到該事務執(zhí)行前的狀態(tài)。觸發(fā)器可用于各種數(shù)據(jù)規(guī)則、約束和默認值的完整性檢查,也可完成更復雜的數(shù)據(jù)檢測和業(yè)務邏輯規(guī)則。
1.1 觸發(fā)器分類
按照觸發(fā)事件的不同,SQL Server觸發(fā)器可以分為DDL(Data Definition Language)觸發(fā)器和DML(Data Manipulation Language)觸發(fā)器兩種。
1)DDL觸發(fā)器用于處理相應的DDL事件。DDL事件有數(shù)據(jù)庫系統(tǒng)用戶登錄與退出和CREATE、DROP、ALTER語句等操作。DDL觸發(fā)器可用于審核與規(guī)范數(shù)據(jù)庫中對表結(jié)構(gòu)、視圖結(jié)構(gòu)上的操作,還可被用于應用系統(tǒng)管理任務。當數(shù)據(jù)庫結(jié)構(gòu)或表結(jié)構(gòu)發(fā)生變化時激發(fā)觸發(fā)器,觸發(fā)器能記錄相應的修改過程,并能禁止用戶刪除指定表、限制用戶對數(shù)據(jù)庫修改等操作。
2)DML觸發(fā)器用于響應用戶DML操作事件。DML操作事件是指針對表或視圖的INSERT、DELETE和UPDATE操作語句。該類觸發(fā)器在DML編輯數(shù)據(jù)時觸發(fā)執(zhí)行,在處理表或視圖中數(shù)據(jù)時DML觸發(fā)器檢查操作是否滿足相應業(yè)務規(guī)則,使得數(shù)據(jù)完整性進一步擴展。
根據(jù)觸發(fā)器是在觸發(fā)操作語句前還是后執(zhí)行的不同,觸發(fā)器又分為INSTEAD OF觸發(fā)器和AFTER(FOR)觸發(fā)器兩種。
1)INSTEAD OF觸發(fā)器。顧名思義,該種觸發(fā)器在數(shù)據(jù)操作之前執(zhí)行,代替操作數(shù)據(jù)的相關(guān)語句,實際上是執(zhí)行觸發(fā)器中的代碼。該類觸發(fā)器定義在視圖或表上。在視圖或表上,每個DELETE、UPDATE和INSERT語句只可定義一個INSTEAD OF觸發(fā)器。
2)AFTER(FOR)觸發(fā)器。在DML語句操作數(shù)據(jù)完成以后被觸發(fā)執(zhí)行。此種觸發(fā)器可對被操作的數(shù)據(jù)進行業(yè)務規(guī)則檢查,如果違反相應的業(yè)務規(guī)則,則返回該數(shù)據(jù)操作前的狀態(tài)。只能在表上而不能在視圖上定義AFTER(FOR)觸發(fā)器,在同一張數(shù)據(jù)表上可定義多個AFTER(FOR)觸發(fā)器。
1.2 DBMS生成的兩個臨時表
在執(zhí)行DML觸發(fā)器時,SQL SERVER生成兩個只讀型臨時表:deleted表和inserted表。在觸發(fā)器執(zhí)行時這兩個表才存在于內(nèi)存,其表結(jié)構(gòu)與激發(fā)DML觸發(fā)器的視圖或基表類似。
1)deleted表
deleted表僅存放進行本次UPDATE和DELETE語句操作的基表的舊數(shù)據(jù)行。執(zhí)行UPDATE或DELETE語句時,該數(shù)據(jù)行從基表中移動到deleted表并從基表中刪除。
2)inserted表
inserted表僅存放進行本次UPDATE和INSERT語句操作的新數(shù)據(jù)行。執(zhí)行UPDATE語句或INSERT語句時,新數(shù)據(jù)行被插入基表的同時也被復制到inserted表中。
實際上,UPDATE操作可看做由DELETE操作和INSERT操作組合而成的。UPDATE操作時,DBMS將要修改的數(shù)據(jù)行從基表中刪除并移到deleted表中,然后將修改后的新數(shù)據(jù)行同時插入到inserted表和基表中。
2 SQL Server觸發(fā)器應用
觸發(fā)器機制類似Windows系統(tǒng)的消息響應機制,我們可以靈活利用這一點,不僅可以在數(shù)據(jù)表上實施比CHECK約束、外鍵約束等更為復雜的檢查和操作,可以引用數(shù)據(jù)庫中其他表中的字段,具有更精細和更強大的數(shù)據(jù)控制能力,還可以利用DDL觸發(fā)器對數(shù)據(jù)庫應用系統(tǒng)實施各種應用控制,提高數(shù)據(jù)庫應用系統(tǒng)的安全性。
2.1實現(xiàn)CHECK約束檢查功能
在DML觸發(fā)器中可以靈活、編寫代碼處理相應的業(yè)務邏輯,因此DML觸發(fā)器可以設(shè)置比CHECK約束更復雜、更強大的相應數(shù)據(jù)檢查規(guī)則。例如醫(yī)院所用某種藥品已經(jīng)停止采購,但此藥品還需在藥品數(shù)據(jù)表中存在,此時需要阻止門診醫(yī)生開列此藥,數(shù)據(jù)庫管理人員就可以在藥品數(shù)據(jù)表上建立相應的觸發(fā)器,來禁止醫(yī)師修改已停止采購藥品的數(shù)據(jù),此任務無法使用CHECK約束來完成。當數(shù)據(jù)庫系統(tǒng)設(shè)計者想控制錯誤信息或者給用戶/客戶應用程序傳遞錯誤信息時,無法使用CHECK約束實現(xiàn),而觸發(fā)器就能很好地完成任務。當需要發(fā)出更詳細的錯誤信息以提示用戶時,數(shù)據(jù)庫系統(tǒng)設(shè)計者可以在觸發(fā)器中使用RAISERROR()函數(shù)來達到目的。當在業(yè)務邏輯需要使用另一張表的數(shù)據(jù)時,也可以使用觸發(fā)器來實現(xiàn)。觸發(fā)器與CHECK約束各有優(yōu)勢。CHECK約束執(zhí)行快且效率高,但只能引用同一表中的數(shù)據(jù),而觸發(fā)器卻可以引用不同表中的數(shù)據(jù)。觸發(fā)器可以完全實現(xiàn)CHECK約束的所有功能,但在效率上并不總是比CHECK約束好。觸發(fā)器是維護引用完整性需要的一種最好選擇,雖然它們的速度有點慢,但在維護數(shù)據(jù)完整性上更靈活。何時選擇使用觸發(fā)器與CHECK約束,需要根據(jù)實際情況定,首選CHECK約束,當CHECK約束無能為力時就用觸發(fā)器。
2.2 數(shù)據(jù)庫設(shè)計與批量數(shù)據(jù)導入
數(shù)據(jù)庫設(shè)計時,要在表上設(shè)計各種約束以及要設(shè)計表與表之間的引用關(guān)系等等。在數(shù)據(jù)庫系統(tǒng)調(diào)試中難免會對表結(jié)構(gòu)進行改變完善,此時在原表上所建立的各種完整性約束都需要刪除,在更改表結(jié)構(gòu)建立表后,再重新建立各種約束,上述工作較難保證沒有差錯或遺漏,這就給數(shù)據(jù)庫設(shè)計者帶來較大不便??梢允褂糜|發(fā)器來建立相關(guān)約束規(guī)則,在表結(jié)構(gòu)發(fā)生更改時只需禁用觸發(fā)器即可,隨后也可方便地恢復觸發(fā)器的使用,方便數(shù)據(jù)庫設(shè)計和調(diào)試。在數(shù)據(jù)庫系統(tǒng)開發(fā)完畢后再將某些觸發(fā)器改為DRI(聲明引用完整性)。當需要大批量導入數(shù)據(jù)時,往往需要關(guān)閉各種約束來方便導入數(shù)據(jù);當使用觸發(fā)器實現(xiàn)數(shù)據(jù)約束時,就能體現(xiàn)出觸發(fā)器的優(yōu)點。只需關(guān)閉觸發(fā)器就可減少導入時的大量開銷以實現(xiàn)批量數(shù)據(jù)的快速導入。
2.3 UPDATE()函數(shù)和UPDATE_COLUMNS()函數(shù)
在UPDATE觸發(fā)器中,經(jīng)常通過查看感興趣的列是否通過發(fā)生改變來限制觸發(fā)器中實際執(zhí)行的代碼數(shù)量,要完成這個任務,可以利用UPDATE()函數(shù)和UPDATE_COLUMNS()函數(shù)。
1)UPDATE()函數(shù)
該函數(shù)用于測試在指定列上進行的INSERT或UPDATE操作,不能用于DELETE操作,可以指定多列。只適用于觸發(fā)器范圍,其核心目的是對指定列進行是否被更新檢測。
UPDATE(FIELD_NAME)值為true,則意味著FIELD_NAME列被更新。
2.4 加強數(shù)據(jù)庫用戶管理
可以針對 CREATE、ALTER 和 DROP 開頭的語句,建立DDL觸發(fā)器。為防止對數(shù)據(jù)庫架構(gòu)進行某些更改時,當希望數(shù)據(jù)庫中發(fā)生某種情況以響應數(shù)據(jù)庫架構(gòu)中的更改時,當需要記錄數(shù)據(jù)庫架構(gòu)中的更改或事件時,使用DDL觸發(fā)器進行管理??梢詫γ艽a表中指定列設(shè)定AFTER(FOR)DML觸發(fā)器,當表中用戶名或密碼值發(fā)生變化時,將操作者、操作時間、操作對象、前后變化的數(shù)據(jù)等內(nèi)容進行保存并向數(shù)據(jù)庫管理員發(fā)通知,為及時發(fā)現(xiàn)不合法操作、加強系統(tǒng)審核、保障數(shù)據(jù)庫的安全提供幫助。
3 SQL Server觸發(fā)器應用注意事項
3.1 觸發(fā)器執(zhí)行是被動的而不是主動的
這里主要指AFTER觸發(fā)器發(fā)生在事件發(fā)生之后,在觸發(fā)器被激活時,整個觸發(fā)語句已經(jīng)執(zhí)行而且事務已經(jīng)記錄在日志中了(但沒有提交)。這意味著,如果觸發(fā)器需要rollback,就不得不撤銷已經(jīng)完成的大量工作,因此促發(fā)其對系統(tǒng)性能的影響程度取決于觸發(fā)語句工作量的大小。而約束是主動的,約束是在實際語句發(fā)生之前執(zhí)行的,這意味著它們在所有主要工作完成前阻止失敗的事情發(fā)生。也就意味著約束的運行速度要快一些。特別是觸發(fā)語句越復雜、影響數(shù)據(jù)量越大,使用觸發(fā)器所帶來的效率影響也越大。
3.2 盡量保持觸發(fā)器簡潔
觸發(fā)器是與所調(diào)用的語句所在事務的一部分。這意味著語句要到觸發(fā)器結(jié)束時才完成。如果在觸發(fā)器的語句體中書寫了運行很長時間的代碼,就意味著引起觸發(fā)器觸發(fā)的每段代碼,運行時間都很長。因此這很可能使得應用程序執(zhí)行效果較差。
3.3 盡量不要在觸發(fā)器中回滾
做到這一點較為困難,因為回滾是在觸發(fā)器中通常希望完成的主要任務。最典型的觸發(fā)器——AFTER觸發(fā)器——發(fā)生在大部分操作已經(jīng)完成以后,這也意味著回滾開銷很大,這也是為什么建議盡可能使用DRI的原因。如果在觸發(fā)器中使用多條ROLLBACK TRAN語句,最好在執(zhí)行激活觸發(fā)器的語句之前預先找到錯誤。在錯誤發(fā)生前進行測試,不要等到回滾的時候。
4 結(jié)束語
靈活使用觸發(fā)器可以幫助數(shù)據(jù)庫系統(tǒng)設(shè)計者和維護者實現(xiàn)許多復雜的功能,能較好地提高信息系統(tǒng)的數(shù)據(jù)完整性。但要慎用觸發(fā)器,如果濫用會造成數(shù)據(jù)庫系統(tǒng)的維護困難。因此在數(shù)據(jù)庫系統(tǒng)設(shè)計中,盡量使用DRI來保證數(shù)據(jù)完整性。合理的觸發(fā)器設(shè)計既可以保護表中的數(shù)據(jù),使數(shù)據(jù)表更加安全,又可以減少數(shù)據(jù)庫設(shè)計者的勞動強度,具有事半功倍的作用。
參考文獻:
[1] 張峰. 觸發(fā)器在數(shù)據(jù)處理過程中的應用研究[J].計算機工程與科學,2008(5).
[2] 李霞. SQL Server約束在維護數(shù)據(jù)完整性中的運用[J].晉城職業(yè)技術(shù)學院學報,2012(5).