2010-10-22 72 views
5

我有一個表的控制,類似UNIQUE約束由位柱

FieldsOnForms(
FieldID int (FK_Fields) 
FormID int (FK_Forms) 
isDeleted bit 
) 

對(FieldID,FormID)應該是唯一的,但僅當該行沒有被刪除(請將isDeleted = 0)。

是否可以在SQLServer 2008中定義這樣的約束? (不使用觸發器)

P.S.設置(FieldID,FormID,isDeleted)爲唯一添加了將一行標記爲已刪除的可能性,但是我想有機會將n行(每個FieldID,FormID)設置爲isDeleted = 1,並且只有一行請將isDeleted = 0

回答

12

你可以有一個獨特的指數,使用SQL Server 2008 filtered indexes功能,也可以對視圖應用唯一指數(窮人的篩選指標,工作針對早期版本),但你不能有如你所描述的一個UNIQUE約束。

過濾索引的例子:

CREATE UNIQUE NONCLUSTERED INDEX IX_FieldsOnForms_NonDeletedUnique ON FieldsOnForms (FieldID,FormID) WHERE isDeleted=0 
+0

+1最佳答案... – gbn 2010-10-22 16:55:44

+0

雖然我有一些錯誤,由於位字段(轉換列常數的數據類型不支持篩選索引),這似乎是我正在嘲笑的解決方案。 – jaraics 2010-10-26 07:47:56

+0

@jaraics - 我剛剛在你的問題中創建了表格,然後在我的答案中創建了索引,並創建了沒有錯誤的表格。此外,如果遇到數據類型不匹配,通常將CAST(或CONVERT)常量更改爲列的類型,而不是相反。不知道這是否能解決您的問題。 – 2010-10-26 07:55:40

1

沒有,唯一的方式非常獨特。您必須將已刪除的記錄移到另一個表中,或將IsDeleted更改爲在所有已刪除記錄(例如時間戳)中可以唯一的東西。任何一種解決方案都需要在應用程序,存儲過程或觸發器中進行額外的工作。

2

您可以將您的IsDeleted列更改爲DeletedDate,並將其作爲DATETIME,並將該行作爲邏輯刪除行的確切時間。或者,您可以添加一個DeletedDate列,然後根據該列創建一個IsDeleted計算列,以便在代碼中使用該列時仍然可以使用該列。當然,您將在DeletedDate(除了FieldID和FormId)上放置一個唯一索引,而不是IsDeleted列。這將允許一個NULL列。

Albin發佈了一個類似於此的解決方案,但隨後將其刪除。我不知道爲什麼,但如果他重新發布它,那麼他在我之前就在這裏。 :)

+0

這似乎是早期SQL服務器的一個很好的選擇。 – jaraics 2010-10-26 07:50:05