2014-02-16 20 views
0

在SQL Server 2012中,我有一個包含四列的「交叉引用」表。四列的組合必須是唯一的。我最初的想法是簡單地創建一個包含所有四列的主鍵,但一些研究表明,這可能不是一個好主意。如何針對四列實施唯一性

問題的背景... 我想在遺留的web應用程序上實現標記服務。一些需要標記的對象使用uniqueidentifier作爲其主鍵,而另一些使用簡單的整數ID。我已經用「兩張桌子」的方式來解決這個問題。一個表格包含標籤,而另一個表格提供待標註對象與標籤表格之間的參考。此表我的名字標記列表...

CREATE TABLE TagList (
    TagId   nvarchar(40)  NOT NULL, 
    ReferenceGuid uniqueidentifier NOT NULL, 
    ReferenceId int    NOT NULL, 
    ObjectType  nvarchar(40)  NOT NULL 
) 

例如,用字「示例」唯一標識符的主鍵標記對象,標記列表記錄是這樣的:

TagList (
    TagId   'example', 
    ReferenceGuid '1e93d578-321b-4f86-8b0f-32435d385bd7', 
    ReferenceId 0, 
    ObjectType  'Customer' 
) 

要標記用字「示例」的整數主鍵的對象,標記列表記錄是這樣的:

TagList (
    TagId   'example', 
    ReferenceGuid '00000000-0000-0000-0000-000000000000', 
    ReferenceId 5639, 
    ObjectType  'Product' 
) 

在實踐中,無論是標籤識別和ReferenceGuid列必須是唯一的, ,如果定義了一個int主鍵對象,則TagId,ReferenceId和ObjectType必須是唯一的。

爲了簡化(?)事情,使所有四列的組合都是唯一的,也可以達到相同的功能目的。

任何意見,將不勝感激。

+0

ObjectType如何與引用guid和引用id相關?讓我知道在這兩列上是否存在對象類型的函數依賴關係? –

+0

就定義而言,在定義具有唯一標識符主鍵的對象時,對象類型不是絕對必要的。當用整數主鍵定義一個對象時,對象類型區分一個ID和另一個ID,例如,比方說,27號可以指產品或客戶,對象類型定義了哪一個。對象類型也用於標籤搜索:找到所有標籤爲'example'的客戶 – Neilski

回答

2

具有多列主鍵應該做的伎倆

CREATE TABLE TagList (
    TagId   nvarchar(40)  NOT NULL, 
    ReferenceGuid uniqueidentifier NOT NULL, 
    ReferenceId int    NOT NULL, 
    ObjectType  nvarchar(40)  NOT NULL, 
    CONSTRAINT pk_TagList PRIMARY KEY (TagId,ReferenceGuid,ReferenceId,ObjectType) 
) 
+0

嗨,李,這是我原來的計劃,但是當我調查這個時,我發現幾個帖子暗示這種方法不適合性能方面的原因,最好引入代理主鍵(例如,標識整數),並添加特定索引來控制TagId + ReferenceGuid或TagId + ReferenceId + ObjectType的「唯一性」。當然你的建議似乎更簡單。 – Neilski

+0

嗨,對不起,我沒有完全閱讀你的問題,這樣做有一個約束將強制進入唯一性,因爲有一個額外的條目來管理身份將依賴ReferenceGuid和ReferenceId被輸入爲唯一的每一次。 我想看看你的結構,你不需要你的約束中的所有四個ReferenceGuid&ReferenceId? 我個人也會將ObjectType拉出到一個單獨的表中,該錶鏈接到一個ObjectTypeId外鍵上的TagList。 –

+0

如果ReferenceId是增量式的,我會建議把它放在主鍵的開頭。如果您沒有手動設計CLUSTERED索引,它將與PRIMARY KEY相同。如果ReferenceId是增量式的,那麼每一個新行都將被存儲在表的末尾(實際上在頁面的結尾處)。如果TagId將是第一個,並且這是字母數字無序實體,那麼每個新行將被「隨機」存儲在表的中間(實際上在頁面中間) - 因此可能會出現頁面碎片。 – huhu78

1

如果你只需要一個唯一約束,而不是一個主鍵,這可用於:

ALTER TABLE TagList 
ADD CONSTRAINT UK_TagList_1 UNIQUE 
(
    TagId, 
    ReferenceGuid, 
    ReferenceId, 
    ObjectType 
) 
1

我不有所涉及的實體的所有信息,但與我有限的知名度,我會嘗試建議下面的第一個切割設計:

創建兩個單獨的表,其中一個與TagId和參考ceGuid和其他與TagId和ReferenceId。雖然我不確定ObjectType。如果ObjectType不是隱式的,那麼這兩個表都可以維護它。然後可以在這些表的頂部創建一個視圖來拍攝可以包含所有必需列的查詢。 這樣我們就可以解決當前設計中的空間浪費問題。 如果這個設計沒有解決問題,請給出您的意見。

+0

謝謝Dipendu,這是類似於上面提出的最終方法,看起來像一個更清潔/更好的結構化方法。 – Neilski