2013-01-08 71 views
1

我在我的SQL Server(2008)數據庫中有一個非有向圖表,我想約束來防止重複。 我的鏈接表有2列,(城市1,城市2),這兩個整數引用到城市表中。我可以使用以下內容:非有向圖的唯一約束格式 - 給定(1,2),阻止(2,1)

ALTER TABLE dbo.CityConnections 
ADD CONSTRAINT CK_CityConnections_OneWayOnly UNIQUE (City1, City2) 

這是我想要的一半,但這並不妨礙添加「反向」連接。

谷歌給我

... UNIQUE (MIN(City1,City2), MAX(City1,City2)) 

它看起來像它會做我想要什麼,但語法是無效的。

我也嘗試過使用CASE的複雜約束,但我無法得到正確的語法。

我該如何做到這一點?

回答

4

假設您可以控制您對錶格的輸入,以下內容應該可以工作;

ALTER TABLE dbo.CityConnections 
ADD CONSTRAINT CK_CityConnections_Unq UNIQUE (City1, City2) 
ALTER TABLE dbo.CityConnections 
ADD CONSTRAINT CK_CityConnections_OneWayOnly CHECK (City1 < City2) 
+0

+1。這就是我通常會推薦的。或者,可以添加觸發器,以便插入和更新可以按任一順序工作。 –

+1

只是爲了完整性,我觸發看起來是這樣的: 'CREATE TRIGGER TRIG_CityConnection_Insert ON [CityConnections] INSTEAD INSERT 作爲 BEGIN \t SET NOCOUNT ON; \t INSERT [CityConnections] \t選擇(CASE當[City1] <[City2] THEN [City1] ELSE [City2] END)爲City1,(CASE當[City1]> [City2] THEN [City1] ELSE [City2 ] END)as City2 \t FROM inserted; END' – Taoist

0

好極了,只要我問一個令我困惑的問題,我就會得到靈感,並自己想出來。 我的解決辦法是添加計算列,並使用這些作爲唯一約束(指數)

我現在有:

CREATE TABLE [CityConnections] 
(
    [City1] [int] NOT NULL, 
    [City2] [int] NOT NULL, 
    [minCity] AS (case when [City1]<[City2] then [City1] else [City2] end), 
    [maxCity] AS (case when [City1]>[City2] then [City1] else [City2] end), 
CONSTRAINT [CK_CityConnections_OneWayOnly] UNIQUE NONCLUSTERED 
(
    [minCity] ASC, 
    [maxCity] ASC 
) 

編輯 - 進一步的思考(和評論)後,我同意這是不是最好的解決方案

+1

爲支持'CK_CityConnections_OneWayOnly'而創建的索引在這裏完全被浪費了,除非你的查詢引用了'minCity,maxCity',並且他們爲什麼要存儲'City1,City2'呢? MarkD的答案似乎更有效率。 –

+1

「下面的答案」是一個很好的方法來引用這裏的答案 - 答案根據投票改變立場。如果你想引用他人的答案,通常最好*鏈接*答案(每個答案下面有一個共享鏈接,你可以複製一個適當的鏈接地址) –

+0

其實,在進一步考慮我同意 計算列是一團糟(我寧願在約束條件下計算它們) 另外,正如你所指出的那樣,約束條件實際上變成了一個無效的索引 – Taoist