SQL解發器,雖然對它有一定認識,但自從我工作這近四年來,還沒有寫過解發器,我想也有很多朋友像我一樣,雖然經常使用ado.net,但無非都是些增刪改查的操作。解發器的應用比起預存程序可謂要少的多,至到時最近的一個項目需求,讓我想到瞭解發器的應用情境。
往往一個公司的IT部門會根據職能或者是業務劃分,每個部門負責一部分功能模組,部門之間即獨立也有聯絡,當其它部門所做的功能不能完全滿足你的需求時,你有可能需要自己動手來協助完善其功能。
具體例子:部門A負責酒店的業務,所有酒店查詢,訂單處理都由他們完成,酒店都有統一的庫存管理,但有的酒店比較特殊,可以用積分來換,但這種酒店的庫存和正常的酒店庫存並不統一,唯一的共同點就是積分兌換的酒店價格與正常酒店價格存在一個比例,例如正常酒店(北京飯店)一晚100元,那麼積分酒店(北京飯店)就需要100*100積分。原來積分兌換的酒店價格都由系統錄入時手工指定價格,但現在業務變更,需要在錄入積分酒店時,自動初始化價格,這個價格就要以對應的正常酒店價格為準。
問題:初始化價格如何取?
方法一:修改錄入積分酒店的程式。
優點:處理方便,在錄入資料時,先查詢到對應正常酒店的價格,然後一併寫入資料庫。
缺點:需要其它人支援,如果此段程式無人維護,處理難度會非常大。
方法二:給原來程式額外打一個補丁。在資料錄入資料庫後,利用觸發器自動初始化價格。
優點:只需要額外增加一個觸發器,改動量相對小。
缺點:相對方法一的缺點就不值得一說了。
觸發器定義:它是一種類型獨特的過程,非常類似C#中的事件。asp.net中,當點擊一個按鈕,就會觸發相應事件。觸發器與資料庫表相關聯,當表中內容發生如下特殊變化時,觸發器就會被觸發。1:insert;2:update;3:delete。
說明:本文只探討after觸發器,至於instead-of觸發器不在本文討論範圍之內。after觸發器的文法我也略過,重點分享下在應用觸發器時應該注意的地方。
第一:觸發器不會對每條記錄都觸發一次。例如我們在一次事務中更新或者刪除了一條以上的記錄,觸發器只會觸發一次,但能正常反映所有受影響的行。
第二:使用觸發器一定要清楚兩個虛似表:
1:inserted,事務中被插入的所有記錄。
2:deleted,事務中被刪除的所有記錄。
說明:資料庫中不存在updated表,因為資料的更新是先刪除然後插入的過程。有了上面兩個虛似表,我們就可以在受影響的行上做其它操作,例如在錄入積分酒店資料後,利用inserted中的資料資訊來更新本記錄的某些欄位值。
第三:after,從字面意義來看應該是某個操作之後的意思,after觸發器就是資料成功插入資料表後執行的操作,如果插入資料失敗,對應的觸發器是不會引發的。
第四:觸發器與開發人員在對於什麼樣才是對錶的成功操作概念文件上有不同的定義,當更新或者是刪除0條記錄時,觸發器也會被觸發,但對於開發人員來說,顯然這種觸發是沒有意義的。此種觸發第一是沒有意義,第二是佔用系統資源,如果你的資料服務器非常繁忙,而且有使用者正在鎖定資料庫表,執行觸發器的時間往往比你想象的要多。所以我們希望遇到這種情況應該儘快退出觸發器。我們可以用如下代碼來完成,此代碼一定要在解發器語句的開頭部分體現,否則@@rowcount會受到前面代碼的影響。
IF @@rowcount = 0
BEGIN
PRINT '觸發器退出'
RETURN
END
第四:不要在預存程序中使用select以及print語句,雖然這兩個語句在調試過程中非常好用,但最好不要體現在正式上線環境中,這些語句會產生另外的結果集,如果沒有正常處理它們,或者是沒有預料到它們的出現,那麼這種結果集有可以影響到用戶端應用程式的失敗。
第五:觸發器管理。
1:利用sp_helptrigger命令來查看一個表關聯的觸發器。sp_helptrigger 表名
2:利用sp_helptext命令來查詢某一個觸發器的代碼。sp_helptest 觸發器名。
3:刪除觸發器,和刪除資料庫其它對象類似,drop trigger 觸發器名。
4:修改觸發器和產生觸發器內容差不多,只不過修改的語句為alter trigger。
5:利用exec sp_rename命令來完成觸發器的重新命名。
第六:觸發器中的交易管理。觸發器始終是對它進行初始化事務的一部分,這個事務可以是顯式的也可以是隱式的。可以在觸發器中使用如下指令碼來復原之前的資料操作。在這之前的代碼中並不一定要顯示的寫begin transaction之類的代碼。
IF @@ERROR <> 0
BEGIN
ROLLBACK TRANSACTION
END
第七:觸發器的執行順序,對於after觸發器來說,一個表可以對應多個after觸發器,眾多觸發器如何來控制它們的執行順序呢?我們可以利用exec sp_settrggerorder命令來完成,示命如下:
代碼
exec sp_settriggerorder @triggername=觸發器名稱,
@order='first,或者是last或者是none',
@stmttype='資料操作類型,例如insert,update或者是delete'
第八:哪些情況下根本不需要使用觸發器:
1:如果能夠使用約束實現的功能,就不要使用觸發器。
2:如果可以使用預存程序來完成,那麼也不分使用觸發器。
說明:觸發器的實現,調試,管理比起預存程序都更加困難,如果有更好的方式實現你的需求最好不要使用觸發器,除非沒有比觸發器更簡單的方法。
總結:
選擇好適當的情境,觸發器往往會有意想不到的效果。本篇文章只提到了after觸發器一些比較實用的知識,至於具體應用大家仁者見仁,智者見智。
作者:薑敏
出處:http://www.cnblogs.com/aspnet2008/