2013-03-01 59 views
0

我想用複合鍵創建表,其組合必須是唯一的。複合鍵的獨特組合

例如,

CREATE TABLE [dbo].[TEST3](
    [field1][int] NOT NULL, 
    [field2][int] NOT NULL 
PRIMARY KEY (field1,field2) 
) 
GO 

行:

field1 field2 
---------------- 
    1  2 
    2  1 

如何防止這種行爲?我需要在用戶插入行(2,1),其已經具有行的表有錯誤(1,2

+3

最簡單的方法是添加檢查約束,確保它們始終以一致的順序輸入。例如'CHECK(field1 2013-03-01 15:43:22

回答

2

您可以做到這一點使用用戶定義類型,但恕我直言,這聽起來像一個糟糕的設計和可能是一個XY問題。

如果你正在嘗試創建一個多對多的表格(例如,一個共同朋友的表格),我會建議使用檢查約束來始終確保field1嚴格小於field2

您甚至可以更進一步,並需要使用存儲過程來插入行,或創建一個觸發器INSTEAD OF INSERT。這會讓你按照正確的順序排列,這樣你就不必依靠前端知道列應該在哪個順序。

+0

此外,爲什麼不使用存儲過程來插入數據?採取兩個參數,執行存儲過程中的邏輯,先把兩個中的較小者,檢查重複項等。 – 2013-03-01 15:49:59

+1

@KyleHale Heh剛剛編輯了我的答案以包含它。你打了我約10秒:) – 2013-03-01 15:50:59

+0

我應該說,我的領域的類型是(uniqueidentifier)。我可以比較這種類型的字段嗎? – user1561325 2013-03-01 15:57:53

1

一些插入(和更新)觸發器將是可能的解決方案,即

create trigger prevent 
on TEST3 
for insert 
as 
if (select count(1) 
    from TEST3, inserted 
    where TEST3.field1=inserted.field2 and TEST3.field2=inserted.field1) > 0 
/* Cancel the insert and print a message.*/ 
    begin 
    rollback transaction 
    print "Failed." 
    end 
/* Otherwise, allow it. */ 
else 
    print "Added!" 
+0

僅供參考這是一個角落案例,但我相信這個觸發器仍然會允許我執行插入測試3值(1,2),(2,1)' – 2013-03-01 15:56:17

+0

對不起,但我不明白'角落案例'是什麼意思這裏。請解釋一下。另外我無法測試你的情況,因爲在我使用的ASE中,這種多重插入是不允許的。但我確信這個觸發器應該在其他RDBMS中正常工作。 – www 2013-03-01 16:18:33

+0

轉角情況是一種非常不可能的情況,可能會產生意想不到的結果。在這種情況下,極有可能不會有人使用相同的兩個ID向後進行多次插入。但是,這是可能的,並且在完成時會產生讓查詢通過的意外結果。 – 2013-03-01 16:25:29