日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

【译】如何使用索引视图和一个只有2行的表限制业务规则

發布時間:2025/7/14 编程问答 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 【译】如何使用索引视图和一个只有2行的表限制业务规则 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

??? 假設一個業務規則規定某些情況不允許存在.并且不允許使用外鍵進行限制,此時Instead of 觸發器可以作為備選答案,但是通常這類觸發器在以后帶來的麻煩會多于其帶來的便利。還有一種解決方式是使用包含唯一索引的索引視圖與只有一個兩行的dummy table進行連接。

???? 假設你有如下兩個表,地區和辦事處

?

Region表

???

RegionIdRegionNameIsActiveEffectiveDateExpirationDate
1East11/1/2009NULL
2West11/1/2009NULL
3North11/1/2009NULL
4South11/1/2009NULL
5Antarctica11/1/2009NULL

?

Office表

RegionIdRegionIdOfficeNameIsActiveEffectiveDateExpirationDate
11New York11/1/2009NULL
22Los Angeles11/1/2009NULL
33Minneapolis11/1/2009NULL
44Atlanta11/1/2009NULL
55Byrd Station11/1/2009NULL

?

你如何保證活動的(IsActive=1)的Office只屬于活動的Region?

??? 上面提到的表需要某種參照完整性.RegionId是Office表的外鍵,Check約束保證了在ExpirationDate不為Null的情況下,永遠不會是1.但是我們如何防止IsActive的的Office屬于IsActive=0的Region呢?我們可以重新設計表或是使用Instead of觸發器,但更方便的做法是使用一個含有唯一索引的索引視圖與一個兩行的啞表進行連接。

?

DuplicateRows table

??? DuplicateRows表包含兩行,如下

DuplicateRowIndexDuplicateRowValue
1Duplicate Row
2Duplicate Row

?

??? 對于這個表的唯一要求是這個表至少含有兩行,其結構和內容并不重要。這個表甚至也可以是只有一列的表并且每行的值不一樣。而我這里用這種方式命名是因為“Duplicate Row”這個名字看起來不容易產生混淆,并且這樣的命名也不會使得其它DBA刪除這個表。

?

InvalidRegionIsInactiveButOfficeIsActiveView視圖

??? 業務規則是如果區域(Region)是不活動的,不能存在活動的辦事處(Office)與其關聯。換句話說,不能在屬于某個區域的辦事處還是active的情況下關閉這個區域,除非設置IsActive為0或是將這個辦事處分到其它區域(Region),下面的View顯示了顯示了Region的IsActive為0并且屬于它的offce的IsActive為1的例子。這違背了預設的業務規則.與dbo.DuplicateRows進行Cross Join是為了實現如果Where子句滿足條件,最少返回兩行。

CREATE View dbo.InvalidRegionIsInactiveButOfficeIsActiveView With SchemaBindingAsSELECT dbo.Region.RegionId FROM dbo.Region INNER JOIN dbo.Office ON dbo.Region.RegionId = dbo.Office.RegionId CROSS JOIN dbo.DuplicateRows WHERE dbo.Region.IsActive = Convert(bit, 0) AND dbo.Office.IsActive = Convert(bit, 1)

??? 最后的畫龍點睛之筆是創建唯一索引,唯一索引是為了防止重復行,但是這個視圖與一個兩行的表進行Cross Join,這使得如果要返回結果,則返回一個兩行的結果.但這又違背了唯一索引,所以這種情況永遠不可能發生。

CREATE UNIQUE CLUSTERED INDEX IX_RegionInvalidOfficeIsActiveView_RegionId ON dbo.InvalidRegionIsInactiveButOfficeIsActiveView(RegionId ASC) WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, SORT_IN_TEMPDB = OFF, IGNORE_DUP_KEY = OFF, DROP_EXISTING = OFF, ONLINE = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]


??? 最后的結果是不會違背業務規則。

?

測試:關閉Antarctica區域

??? 總部的那幫家伙決定關閉Antarctica區域。下面語句在不顧與之關聯的Office的狀態的情況下設置Region的IsActive為0。

UPDATE dbo.RegionSET dbo.Region.IsActive = Convert(bit, 0),dbo.Region.ExpirationDate = GetDate()WHERE dbo.Region.RegionName = N'Antarctica'

??? 當執行后,發生如下錯誤:

Msg 2601, Level 14, State 1, Line 1
Cannot insert duplicate key row in object 'dbo.InvalidRegionIsInactiveButOfficeIsActiveView' with unique index 'IX_RegionInvalidOfficeIsActiveView_RegionId'. The duplicate key value is (5).


??? 在關閉Antarctica區域之前,Byrd Station辦事處必須設置成不活動的或者是分配給其它區域,因為我并不想解雇這個辦事處的任何人,所以我將這個辦事處分為了其它區域。

UPDATE dbo.OfficeSET dbo.Office.RegionId = (SELECT dbo.Region.Regionid FROM dbo.Region WHERE dbo.Region.RegionName = N'South')FROM dbo.OfficeWHERE dbo.Office.RegionId =(SELECT dbo.Region.RegionidFROM dbo.RegionWHERE dbo.Region.RegionName = N'Antarctica')

??? 一旦沒有任何活動的辦事處與Antarctica區域相關聯,我就可以通過Update語句來關閉Antarctica區域了。

?

如何在你的數據庫中實現這個技巧

??? 下面幾部幫助你在數據庫中實現這個技巧:

??? 1.創建dbo.DuplicateRows table表并插入兩條數據

??? 2.寫一個違反了業務規則并且還能返回結果的查詢

??? 3.在這個查詢中與dbo.DuplicateRows進行Cross Join

??? 4.創建一個包含SchemaBinding參數和上面查詢語句的視圖

??? 5.在視圖上創建唯一索引

?

總結

??? 使用索引視圖和一個兩行的表進行連接或許并不是實現業務規則最有效的手段,但是使用了這種方法可以避免使用復雜的Instead of觸發器。假如微軟提供了“Before觸發器”使得違反業務規則的查詢在執行之前就被取消的話,就不需要我這種手段了。上面的技巧可以看作是一個無奈的人實現的山寨版”before 觸發器”。

?

??? 原文鏈接:http://www.sqlservercentral.com/articles/Business+Rules/91924/

??? Translated by:CareySon

轉載于:https://www.cnblogs.com/CareySon/archive/2012/08/21/2648492.html

總結

以上是生活随笔為你收集整理的【译】如何使用索引视图和一个只有2行的表限制业务规则的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。