新聞中心
SQL Server約束相信大家都比較了解了,那么,SQL Server約束和觸發(fā)器的區(qū)別在哪里呢?

在SQL Server數(shù)據(jù)庫(kù)中提供了兩種主要機(jī)制來(lái)強(qiáng)制使用業(yè)務(wù)規(guī)則和數(shù)據(jù)完整性,他們是SQL Server約束和觸發(fā)器。觸發(fā)器其實(shí)就是一個(gè)特殊類(lèi)型的存儲(chǔ)過(guò)程,可在在執(zhí)行某個(gè)操作時(shí)自動(dòng)觸發(fā)。觸發(fā)器與約束都可以實(shí)現(xiàn)數(shù)據(jù)的一致性。那么他們?cè)谑褂玫倪^(guò)程中,有哪些差異呢?簡(jiǎn)單的來(lái)說(shuō),觸發(fā)器可以實(shí)現(xiàn)約束的一切功能。但是在考慮數(shù)據(jù)一致性問(wèn)題的時(shí)候,首先要考慮通過(guò)約束來(lái)實(shí)現(xiàn)。如果約束無(wú)法完成的功能,則再通過(guò)觸發(fā)器來(lái)解決。兩者從功能上來(lái)說(shuō),他們的關(guān)系如下圖所示:
觸發(fā)器可以包含使用SQL代碼的復(fù)雜處理邏輯。如果單從功能上來(lái)說(shuō),觸發(fā)器可以實(shí)現(xiàn)約束的所有功能。但是由于其自身的種種缺陷,其往往不是實(shí)現(xiàn)數(shù)據(jù)一致性等特定功能的***解決方案??偟膩?lái)說(shuō),只有在約束無(wú)法實(shí)現(xiàn)特定功能的情況下,才考慮通過(guò)觸發(fā)器來(lái)完成。這只是在處理約束與觸發(fā)器操作過(guò)程中的一個(gè)基本原則。對(duì)于他們兩個(gè)具體的差異筆者在下面也進(jìn)行了比較詳細(xì)的闡述。歡迎大家進(jìn)行補(bǔ)充。
差異一:錯(cuò)誤信息的管理上。
當(dāng)違反系統(tǒng)的SQL Server約束規(guī)則時(shí),需要向用戶(hù)返回一定的錯(cuò)誤信息,方便用戶(hù)進(jìn)行排錯(cuò)。約束與觸發(fā)器在遇到問(wèn)題時(shí)都可以返回給用戶(hù)一定的錯(cuò)誤信息。但是,約束只能夠通過(guò)標(biāo)準(zhǔn)化的系統(tǒng)錯(cuò)誤信息來(lái)傳遞錯(cuò)誤消息。如果應(yīng)用程序需要使用自定義消息和較為復(fù)雜的錯(cuò)誤處理機(jī)制,則必須要使用觸發(fā)器才能夠完成。如現(xiàn)在數(shù)據(jù)庫(kù)中有一張產(chǎn)品信息表。為了保證產(chǎn)品的唯一性,要求產(chǎn)品的編號(hào)必須唯一。如果用戶(hù)輸入的產(chǎn)品編號(hào)跟企業(yè)現(xiàn)有的產(chǎn)品編號(hào)有重復(fù)的話(huà),這條產(chǎn)品信息就不能夠被保存。從技術(shù)上來(lái)說(shuō),約束與觸發(fā)器都可以實(shí)現(xiàn)這個(gè)需求。但是,當(dāng)違反這個(gè)唯一性規(guī)則時(shí),他們提供的錯(cuò)誤信息是不同的。
如利用約束來(lái)實(shí)現(xiàn)這個(gè)唯一性控制,那么當(dāng)用戶(hù)輸入重復(fù)的編號(hào)時(shí),則系統(tǒng)會(huì)提示違反了唯一性規(guī)則,不允許保存。但是光憑這條消息的話(huà),可能用戶(hù)還不能夠馬上了解是怎么回事情。有時(shí)候程序員希望能夠返回更加具體的信息。如在產(chǎn)品基本信息表中可能有多個(gè)字段具有唯一性約束,那么用戶(hù)希望知道到底是哪個(gè)字段違反了唯一性約束。如用戶(hù)現(xiàn)在輸入產(chǎn)品編號(hào)為DT001的產(chǎn)品編號(hào)時(shí)出現(xiàn)了這個(gè)錯(cuò)誤。那么用戶(hù)可能希望系統(tǒng)能夠顯示出系統(tǒng)中原來(lái)存在的DT001這個(gè)產(chǎn)品的具體信息,如他的規(guī)格描述、產(chǎn)品名稱(chēng)等等。這可以幫助員工來(lái)判斷自己要建立的產(chǎn)品信息是否真的跟原來(lái)存在的產(chǎn)品信息重復(fù)。還是只是產(chǎn)品編號(hào)的重復(fù)而已。如果要在錯(cuò)誤信息中帶出更加詳細(xì)的信息,則數(shù)據(jù)庫(kù)管理員不得不采用觸發(fā)器來(lái)對(duì)這個(gè)唯一性進(jìn)行控制。因?yàn)橹挥杏|發(fā)器可以返回?cái)?shù)據(jù)庫(kù)管理員自定義的錯(cuò)誤信息;而且還可以實(shí)現(xiàn)比較復(fù)雜的邏輯控制。而約束只能夠范圍系統(tǒng)定義的標(biāo)準(zhǔn)錯(cuò)誤信息。
另外如果違反一些主鍵、外鍵約束的話(huà),系統(tǒng)也只會(huì)提示標(biāo)準(zhǔn)的錯(cuò)誤信息。而不會(huì)提示到底是哪一張表中存在子記錄等等詳細(xì)的錯(cuò)誤信息。這就給用戶(hù)排錯(cuò)的時(shí)候帶來(lái)不必要的麻煩。因?yàn)樗枰热ゲ檎疫@個(gè)約束或者主鍵的名字,然后再去看具體的約束定義才能夠確定到底是哪里出了問(wèn)題。但是普通用戶(hù)往往是不能夠看到約束的具體定義的。故在遇到這種情況時(shí),***也能夠通過(guò)觸發(fā)器來(lái)提供比較詳細(xì)的錯(cuò)誤信息,以提高應(yīng)用程序的友好性。
差異二:性能上的差異分析。
如現(xiàn)在有兩張表,分別為銷(xiāo)售訂單頭與銷(xiāo)售訂單行。在銷(xiāo)售訂單中有一個(gè)訂單ID,它是這張表的主鍵,也是銷(xiāo)售訂單行表的外鍵?,F(xiàn)在如果更改了銷(xiāo)售訂單頭表的主鍵的值,那么必須要保證銷(xiāo)售訂單行表中訂單ID的值也隨之更改。否則的話(huà),銷(xiāo)售訂單頭表與銷(xiāo)售訂單行表就無(wú)法對(duì)應(yīng)起來(lái)。此時(shí)觸發(fā)器與約束都可以實(shí)現(xiàn)類(lèi)似的功能。觸發(fā)器可以將銷(xiāo)售訂單頭ID的更改通過(guò)級(jí)聯(lián)更新的功能傳播給數(shù)據(jù)庫(kù)中其他相關(guān)的表,實(shí)現(xiàn)級(jí)聯(lián)更新。約束也可以實(shí)現(xiàn)類(lèi)似的功能。而且通常情況下,通過(guò)級(jí)聯(lián)引用完整性約束可以更有效的執(zhí)行這個(gè)級(jí)聯(lián)更新。如當(dāng)上面這個(gè)更改發(fā)生后,觸發(fā)器可以禁止或回滾違反引用完整性的更改,從而取消所嘗試的數(shù)據(jù)修改。當(dāng)更改外鍵且新值與其主鍵不匹配時(shí),這個(gè)的觸發(fā)器將生效。但是,數(shù)據(jù)庫(kù)中有一個(gè)現(xiàn)成的解決方案,即FOREIGN KEY 約束通常用于此目的。如果觸發(fā)器表上存在約束,則在 INSTEAD OF 觸發(fā)器執(zhí)行后但在 AFTER 觸發(fā)器執(zhí)行前檢查這些約束。如果違反了約束,則回滾 INSTEAD OF 觸發(fā)器操作并且不執(zhí)行 AFTER 觸發(fā)器。
遇到這種情況后,往往就是兩種處理方式。一是如果要更改的主鍵在其他表中已經(jīng)存在的話(huà),那么就不允許其進(jìn)行更改,系統(tǒng)會(huì)拒絕保存或者回滾用戶(hù)的更改操作。二是如果要更改的主鍵信息在其他表中已經(jīng)存在相關(guān)的記錄,而數(shù)據(jù)庫(kù)管理員又允許其更改的話(huà),為了保證數(shù)據(jù)的一致性,就要出發(fā)級(jí)聯(lián)更新的功能。讓數(shù)據(jù)庫(kù)系統(tǒng)在更改主鍵的同時(shí)自動(dòng)更新其他表中的相關(guān)信息。無(wú)論采取哪種方式,從性能上來(lái)說(shuō),約束的執(zhí)行性能都要高一點(diǎn)。而且系統(tǒng)本身就提供了一些約束規(guī)則,如級(jí)聯(lián)引用完整性約束的等等。故也省去了管理員寫(xiě)觸發(fā)器代碼的工作量。不過(guò)有一點(diǎn)值得說(shuō)明的是,雖然約束的執(zhí)行性能比較高,但是其向用戶(hù)提供的錯(cuò)誤信息確實(shí)非常有限的。如上面***點(diǎn)所說(shuō),系統(tǒng)只提供了一些標(biāo)準(zhǔn)的錯(cuò)誤信息。如果管理員需要向用戶(hù)提供比較詳細(xì)的錯(cuò)誤信息,則需要通過(guò)觸發(fā)器的自定義錯(cuò)誤信息來(lái)實(shí)現(xiàn)。故在用戶(hù)的友好性與數(shù)據(jù)庫(kù)的執(zhí)行性能之間,數(shù)據(jù)庫(kù)管理員需要做出一個(gè)均衡。
差異三:管理維護(hù)的工作量。
由于約束基本上都是數(shù)據(jù)庫(kù)現(xiàn)成的解決方案。無(wú)論是索引約束還是外鍵約束,又或者是check約束。往往在數(shù)據(jù)庫(kù)系統(tǒng)中已經(jīng)有了現(xiàn)成的解決方案。數(shù)據(jù)庫(kù)管理員通過(guò)直接引用這些解決方案即可以實(shí)現(xiàn)特定的功能,而不用再費(fèi)力的編寫(xiě)觸發(fā)器來(lái)實(shí)現(xiàn)。如要實(shí)現(xiàn)表中某個(gè)字段的唯一性約束,則只需要直接在這個(gè)字段上啟用unique約束即可。從而省去了編寫(xiě)觸發(fā)器代碼的時(shí)間。所以通常來(lái)說(shuō),觸發(fā)器的維護(hù)工作量要比約束來(lái)的多。因?yàn)橛|發(fā)器中系統(tǒng)沒(méi)有現(xiàn)成的可以引用,而都需要數(shù)據(jù)庫(kù)管理員通過(guò)實(shí)際清理來(lái)進(jìn)行編寫(xiě)。如果不熟悉編制的話(huà),還很容易引起不必要的錯(cuò)誤。為此,如果單從這個(gè)工作量來(lái)考慮的話(huà),那么數(shù)據(jù)庫(kù)管理員肯定喜歡采用這個(gè)約束,而不喜歡采用觸發(fā)器。
最終的建議:
如果約束能夠?qū)崿F(xiàn)特定的功能,則數(shù)據(jù)庫(kù)***能夠采用約束而不是觸發(fā)器。因?yàn)榧s束能夠提供比較高的執(zhí)行性能,而且數(shù)據(jù)庫(kù)管理員維護(hù)的工作量也會(huì)小得多。如實(shí)體完整性應(yīng)在***級(jí)別上通過(guò)索引進(jìn)行強(qiáng)制,這些索引可以是PRIMARY KEY約束和UNIQUE約束的一部分,或者是獨(dú)立于約束而創(chuàng)建的。域完整性可以通過(guò)CHECK約束進(jìn)行強(qiáng)制,而引用完整性則可以通過(guò)FOREIGN KEY約束進(jìn)行強(qiáng)制。當(dāng)然使用約束的前提是假設(shè)這些約束的功能能夠滿(mǎn)足應(yīng)用程序的功能需求。
如果系統(tǒng)中現(xiàn)成的約束無(wú)法滿(mǎn)足企業(yè)用戶(hù)的需求,如功能無(wú)法滿(mǎn)足或者提供的錯(cuò)誤信息不夠等情況,此時(shí)數(shù)據(jù)庫(kù)管理員就需要通過(guò)觸發(fā)器來(lái)完成。不過(guò)數(shù)據(jù)庫(kù)管理員在編寫(xiě)觸發(fā)器的時(shí)候,仍然可以借鑒相關(guān)約束的實(shí)現(xiàn)方式。而不用從零開(kāi)始,來(lái)重新設(shè)計(jì)觸發(fā)器。另外 觸發(fā)器可以防止一些惡意或錯(cuò)誤的記錄插入、刪除以及更新操作,并強(qiáng)制執(zhí)行比CHECK約束定義的限制更為復(fù)雜的其他限制。其還可以提供比CHECK約束更復(fù)雜一點(diǎn)的功能。如觸發(fā)器可以引用其他表中的列。
可見(jiàn)觸發(fā)器與約束各有各的特點(diǎn)。數(shù)據(jù)庫(kù)管理員要從執(zhí)行性能、維護(hù)工作量、實(shí)現(xiàn)的功能、用戶(hù)友好性等多個(gè)方面出發(fā),選擇合適的處理方式。
【編輯推薦】
SQL Server外關(guān)鍵字約束的定義
修改Sql Server唯一約束
SQL Server視圖的使用
SQL SERVER內(nèi)部函數(shù)大全
sql server表格變量的用法
本文標(biāo)題:SQLServer約束和觸發(fā)器的區(qū)別
分享地址:http://www.5511xx.com/article/dhidgjs.html


咨詢(xún)
建站咨詢(xún)
