2013-11-20 68 views
7

如下表(和樣本數據):SQL Server的條件唯一索引

PK | ClientID | SetID | Title 
----------------------------- 
P1 | C1  | S1 | Title1 
P2 | C1  | S1 | Title1 
P3 | C2  | S2 | Title1 
P4 | C2  | S2 | Title1 
P3 | C1  | S3 | Title2 
P5 | C1  | S3 | Title2 

假設Set屬於Client,我可以有一個獨特的索引約束標題中的客戶端內是唯一的,除了與它是同一組中的兄弟姐妹。

因此,例如,我可以有Title1兩個Clients但不是兩個在一個Client。現在爲Client1,我想要有Title1的第二條記錄,但只有當它與所有其他TitleSetID相同時。

需要注意的是,我使用的是SQL Azure,但我更感興趣的是更普遍的(例如2008 R2/2012)。

編輯:
請注意,我不能改變表的結構。它已經存在,並且背後有一個複雜的業務層。如果我可以解決這個問題,那麼很好,如果不是的話,那麼我可以把它打破。

+0

我看不出你如何去擁有的唯一索引三列允許重複信息。我想這可能會解決只有當你添加例如標識列爲了成爲索引的一部分,但你不能改變表。 – gotqn

+0

我可以添加一列,但不能進行侵入式更改,例如將表分成兩部分。 –

+0

@gotqn。它不一定是一個獨特的索引,這正是我所想的會做的伎倆,只是沒有想出如何! :) –

回答

2

您可以嘗試附加索引視圖。

例如,表:

create table dbo.Test (PK int, ClientID int, SetID int, Title varchar(50), primary key (PK)) 

insert into dbo.Test values 
    (1, 1, 1, 'Title1') 
    ,(2, 1, 1, 'Title1') 
    ,(3, 2, 2, 'Title1') 
    ,(4, 2, 2, 'Title1') 
    ,(5, 1, 3, 'Title2') 
    ,(6, 1, 3, 'Title2') 

視圖和索引:

create view dbo.vTest 
with schemabinding 
as 
    select ClientID, Title, SetID, cnt=count_big(*) 
    from dbo.Test 
    group by ClientID, Title, SetID 
GO 
create unique clustered index UX_vTest on dbo.vTest (ClientID, Title) 
GO 

然後:

insert into dbo.Test values (7, 1, 1, 'Title1') -- will pass 
insert into dbo.Test values (8, 1, 1, 'Title1') -- will pass 
insert into dbo.Test values (9, 1, 2, 'Title1') -- will fail 
insert into dbo.Test values (10, 2, 2, 'Title1') -- will pass 
insert into dbo.Test values (11, 1, 3, 'Title1') -- will fail 
+0

這是我最考慮的路線。謝謝你的時間。 –

0

如果我得到了問題的權利我想補充另一個表SetIDTitle之間具有一個1:1關係和獨特的指數ClientID and SetID

CREATE UNIQUE INDEX [Index_Name] 
ON [dbo].[MyTable]([ClientID ], [SetID]) 
+0

感謝您的建議。我同意這將是一個更好的設置,但不幸的是我沒有選擇改變結構。我的選擇是:添加列(計算?),添加索引,視圖等。 –

0

鏈接添加關於插入/更新觸發器添加怎麼說如果違反規則,則執行檢查並引發失敗異常。 您可以在不更改數據模型的情況下添加這些內容。

+0

我已經考慮過這個,但它感覺有點髒。我正在使用AFTER INSERT DML觸發器來達到真正需要BEFORE INSERT的目的。我使用觸發器來做到這一點的關注是性能。你能提供優點和缺點嗎? –

+0

如果您可以使用觸發器,則可以創建'INSTEAD OF INSERT'觸發器來處理插入並進行檢查。 – gotqn

+0

@gotgn。謝謝,我意識到這一點,但INSTEAD OF觸發器要求我重寫將發生的插入。如果我能夠執行INSERT INTO [table] SELECT * FROM INSERTED',那麼我會很高興,但是我無法用身份來做這件事。 –