比較觸發器和約束

2021-09-30 14:52:20 字數 3050 閱讀 9513

在sql server資料庫中提供了兩種主要機制來強制使用業務規則和資料完整性,它們是sql server約束和觸發器。觸發器其實就是乙個特殊型別的儲存過程,可以在執行某個操作時自動觸發。觸發器與約束都可以實現資料的一致性。那麼他們在使用的過程中,有哪些差異呢?

約束和觸發器在特殊情況下各有優勢。

約束主要被用於強制資料的完整性,約束也能提供比觸發器更好的效能。然而在所能完成的操作,以及完成工作時所能使用約束是有限制的。觸發器則常被用於驗證業務規則,或是更複雜的資料驗證,然而可以對資料的其他地方的資料完成更深入的更新,約束只能對其所在表中的資料,或是在設計時輸入的特定資料進行驗證。這同觸發器形成對比,觸發器可以跨越資料庫甚至伺服器,可以對任何在設計時設定的資料,或從任何表上的其他行為所收集的資料進行檢查。如果所需的訪問許可權被給予所有包含的物件,就可以使用觸發器的這些功能。

簡單的來說,觸發器可以實現約束的一切功能。但是在考慮資料一致性問題的時候,首先要考慮通過約束來實現。如果約束無法完成的功能,則再通過觸發器來解決。兩者從功能上來說,他們的關係如下圖所示:

觸發器可以包含使用sql**的複雜處理邏輯。如果單從功能上來說,觸發器可以實現約束的所有功能。但是由於其自身的種種缺陷,其往往不是實現資料一致性等特定功能的首選解決方案。總的來說只有在約束無法實現特定功能的情況下,才考慮通過觸發器來完成。這只是在處理約束與觸發器操作過程中的乙個基本原則。對於它們兩個具體的差異在下面也進行了比較詳細的闡述。

區別一:錯誤資訊的管理上。

當違反系統的sql server約束規則時,需要向使用者返回一定的錯誤資訊,方便使用者進行排錯。約束與觸發器在遇到問題時都可以返回給使用者一定的錯誤資訊。但是,約束只能夠通過標準化的系統錯誤資訊來傳遞錯誤訊息。如果應用程式需要使用自定義訊息和較為複雜的錯誤處理機制,則必須要使用觸發器才能夠完成。如現在資料庫中有一張產品資訊表。為了保證產品的唯一性,要求產品的編號必須唯一。如果使用者輸入的產品編號跟企業現有的產品編號有重複的話,這條產品資訊就不能夠被儲存。從技術上來說,約束與觸發器都可以實現這個需求。但是,當違反這個唯一性規則時,他們提供的錯誤資訊是不同的。

如利用約束來實現這個唯一性控制,那麼當使用者輸入重複的編號時,則系統會提示違反了唯一性規則,不允許儲存。但是光憑這條訊息的話,可能使用者還不能夠馬上了解是怎麼回事情。有時候程式設計師希望能夠返回更加具體的資訊。這時候就需要用到觸發器了。因為只有觸發器可以返回資料庫管理員自定義的錯誤資訊;而且還可以實現比較複雜的邏輯控制。而約束只能夠範圍系統定義的標準錯誤資訊。

區別二:效能上的差異分析。

相信大家看了下面的例子肯定會對它們在效能上存在的差異有進一步的了解。

如現在有兩張表,分別為銷售訂單頭與銷售訂單行。在銷售訂單中有乙個訂單id,它是這張表的主鍵,也是銷售訂單行表的外來鍵。現在如果更改了銷售訂單頭表的主鍵的值,那麼必須要保證銷售訂單行表中訂單id的值也隨之更改。否則的話,銷售訂單頭表與銷售訂單行表就無法對應起來。此時觸發器與約束都可以實現類似的功能。觸發器可以將銷售訂單頭id的更改通過級聯更新的功能傳播給資料庫中其他相關的表,實現級聯更新。約束也可以實現類似的功能。而且通常情況下,通過級聯引用完整性約束可以更有效的執行這個級聯更新。如當上面這個更改發生後,觸發器可以禁止或回滾違反引用完整性的更改,從而取消所嘗試的資料修改。當更改外來鍵且新值與其主鍵不匹配時,這個的觸發器將生效。但是,資料庫中有乙個現成的解決方案,即foreign key 約束通常用於此目的。如果觸發器表上存在約束,則在 instead of 觸發器執行後但在 after 觸發器執行前檢查這些約束。如果違反了約束,則回滾 instead of 觸發器操作並且不執行 after 觸發器。

在網上查了一下遇到這種情況後,往往有兩種處理方式。一是如果要更改的主鍵在其他表中已經存在的話,那麼就不允許其進行更改,系統會拒絕儲存或者回滾使用者的更改操作。二是如果要更改的主鍵資訊在其他表中已經存在相關的記錄,而資料庫管理員又允許其更改的話,為了保證資料的一致性,就要出發級聯更新的功能。讓資料庫系統在更改主鍵的同時自動更新其他表中的相關資訊。無論採取哪種方式,從效能上來說,約束的執行效能都要高一點。而且系統本身就提供了一些約束規則,如級聯引用完整性約束的等等。故也省去了管理員寫觸發器**的工作量。不過有一點值得說明的是,雖然約束的執行效能比較高,但是其向使用者提供的錯誤資訊確實非常有限的。如上面第一點所說,系統只提供了一些標準的錯誤資訊。如果管理員需要向使用者提供比較詳細的錯誤資訊,則需要通過觸發器的自定義錯誤資訊來實現。故在使用者的友好性與資料庫的執行效能之間,資料庫管理員需要做出乙個均衡。

區別三:管理維護的工作量。

由於約束基本上都是資料庫現成的解決方案。無論是索引約束還是外來鍵約束,還是check約束。往往在資料庫系統中已經有了現成的解決方案。資料庫管理員通過直接引用這些解決方案即可以實現特定的功能,而不用再費力的編寫觸發器來實現。如要實現表中某個欄位的唯一性約束,則只需要直接在這個欄位上啟用unique約束即可。從而省去了編寫觸發器**的時間。所以通常來說,觸發器的維護工作量要比約束來的多。因為觸發器中系統沒有現成的可以引用,而都需要資料庫管理員通過實際清理來進行編寫。如果不熟悉編制的話,還很容易引起不必要的錯誤。為此,如果單從這個工作量來考慮的話,那麼資料庫管理員肯定喜歡採用這個約束,而不喜歡採用觸發器。

建議:

如果約束能夠實現特定的功能,則資料庫最好能夠採用約束而不是觸發器。因為約束能夠提供比較高的執行效能,而且資料庫管理員維護的工作量也會小得多。當然使用約束的前提是假設這些約束的功能能夠滿足應用程式的功能需求。如果系統中現成的約束無法滿足企業使用者的需求,如功能無法滿足或者提供的錯誤資訊不夠等情況,此時資料庫管理員就需要通過觸發器來完成。不過資料庫管理員在編寫觸發器的時候,仍然可以借鑑相關約束的實現方式。而不用從零開始,來重新設計觸發器。另外觸發器可以防止一些惡意或錯誤的記錄插入、刪除以及更新操作,並強制執行比check約束定義的限制更為複雜的其他限制。其還可以提供比check約束更複雜一點的功能。如觸發器可以引用其他表中的列。可見觸發器與約束各有各的特點。要從執行效能、維護工作量、實現的功能、使用者友好性等多個方面出發,選擇合適的處理方式。

比較觸發器和約束

在sql server資料庫中提供了兩種主要機制來強制使用業務規則和資料完整性,它們是sql server約束和觸發器。觸發器其實就是乙個特殊型別的儲存過程,可以在執行某個操作時自動觸發。觸發器與約束都可以實現資料的一致性。那麼他們在使用的過程中,有哪些差異呢?約束和觸發器在特殊情況下各有優勢。約束...

DDL觸發器與DML觸發器比較

dml觸發器 要防止對資料庫架構進行某些更改。希望資料庫中發生某種情況以響應資料庫架構中的更改。要記錄資料庫架構中的更改或事件。僅在執行觸發 ddl 觸發器的 ddl 語句後,ddl 觸發器才會激發。ddl 觸發器無法作為 instead of 觸發器使用。下面的示例顯示如何使用 ddl 觸發器阻止...

如何檢視在某個表上建立的觸發器和約束

select constraint type,constraint name,index name from user constraints select from user constraints t where t.constraint name pk t adminer alter tabl...