2014-02-13 63 views
5

這個問題來自我部門內部的一場辯論,它提出了一個簡單的多對多交叉引用表的最佳方式,該表只包含兩列,而這兩列本身就是其他表中的主鍵。在具有唯一索引但沒有主鍵的SQL Server中創建表的影響是什麼?

有沒有人有具體的證據支持或反對創建一個唯一的索引,但沒有主鍵的表? (替代品詳述如下)。換句話說:有人(特別是MSFT人員)知道SQL Server如何內部唯一地標識a)具有主鍵和b)沒有主鍵的行嗎?

詳細

給定輸入表:

CREATE TABLE Foo (FooID bigint identity(1,1) not null primary key, other stuff...) 
CREATE TABLE Bar (BarID bigint identity(1,1) not null primary key, other stuff...) 

三個基本選項(在所有情況下,假設一個外鍵的FooIDBarID列上創建):

-- Option 1: Compound primary key 
CREATE TABLE FooBarXRef ( 
    FooID bigint not null 
    , BarID bigint not null 
    , PRIMARY KEY (FooID, BarID) 
    , CONSTRAINT FK... etc 
) 

-- Option 2: Independent primary key + unique index 
CREATE TABLE FooBarXRef ( 
    FooBarXRefID bigint identity(1,1) not null primary key 
    , FooID bigint not null 
    , BarID bigint not null 
    , CONSTRAINT FK... etc 
); 
CREATE UNIQUE INDEX I_FooBarXRef_FooBar ON FooBarXRef (FooID, BarID); 

-- Option 3: Unique index, no explicit primary key: 
CREATE TABLE FooBarXRef ( 
    FooID bigint not null 
    , BarID bigint not null 
    , CONSTRAINT FK... etc 
); 
CREATE UNIQUE INDEX I_FooBarXRef_FooBar ON FooBarXRef (FooID, BarID); 

我們幾個人覺得在外部參照表上有一個單獨的身份PK是愚蠢的和r edundant - 並且不必要地在數據庫引擎上引入另一層約束檢查。另一方面,一個成員聲稱多列主鍵是邪惡的(我不同意......但這不是問題)。因此,建議的一個折衷辦法是讓xref表只包含兩個外鍵,並在這些列上定義一個唯一索引,但而不是定義了主鍵。

我懷疑,這樣做將導致SQL Server以產生用於唯一地識別每個行,從而產生相同的冗餘約束彷彿主鍵被明確限定的目的的內部主鍵 - 但是我沒有證據或文檔來支持這一點。 Other questions and answers表示默認情況下不存在內部主鍵(即,不等同於Oracle ROWID);因爲%%physloc%%是當前存儲行的位置的指示符,因此可能會發生變化。我的直覺是,引擎必須創建以唯一標識一行以實現遊標,事務和併發。

+0

我肯定會選擇1。這是一張關係表,所以在這種情況下,複合PK是完全有意義的。像「複合鍵是邪惡的」通用斷言是...邪惡;) –

+0

@RaphaëlAlthaus我同意這兩個計數...但我正在尋找*證據*,替代品2和3明顯不太理想:) –

回答

5

主鍵的概念實際上是關於關係理論;通過跨多個表建立關係來維護參照完整性。默認情況下,SQL Server引擎在構建主鍵時(假設此時不存在聚集索引)創建唯一的聚集索引。

這是聚集索引,在葉級別定義了一個唯一的行。對於具有非唯一聚簇索引的表,SQL Server會在密鑰末尾創建一個4字節的「唯一符號」。

  • TestTable1主鍵
  • TestTable2主鍵&唯一非聚集
  • TestTable3唯一聚集
  • TestTable4主羣集(同表1表3 &,由於一個主鍵可以在非限定聚集索引我更喜歡這個總是定義我想要的結構)。

TestTable2是多餘的,它創建一個唯一的聚集索引來存儲所有記錄在葉級別。然後創建一個獨特的非聚集索引來再次實現唯一性。表中的任何更改都會觸發羣集,然後觸發非羣集。

TestTable1,TestTable3,TestTable4是我書中的一個領域,一個獨特的聚集索引結構被創建。記錄存儲在頁面上的方式沒有物理差異。

但是對於SQL Server複製,所有複製表都需要一個主鍵。如果將來您將使用複製,則可能需要確保所有唯一的聚簇索引都是主鍵。

我似乎無法粘貼我的驗證腳本,所以在這裏他們在加速器上。

http://hastebin.com/qucajimixi.vbs

2

嗯,這一切都取決於要求。據我所知

PRIMARY KEY= UNIQUE KEY+NOT NULL key 

這告訴你的是,你可以有多個

NOT NULL UNIQUE INDEXES(NON CLUSTERED) 
     but 

CANNOT HAVE MULTIPLE PRIMARY KEYS IN A TABLE(CLUSTERED). 

我關係數據庫模型,並與主外鍵關係工作的一個巨大的信徒。數據庫複製要求您在表上有主鍵;因此,爲表創建主鍵而不是UNIQUE鍵總是一個好習慣。

相關問題