這個問題來自我部門內部的一場辯論,它提出了一個簡單的多對多交叉引用表的最佳方式,該表只包含兩列,而這兩列本身就是其他表中的主鍵。在具有唯一索引但沒有主鍵的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...)
三個基本選項(在所有情況下,假設一個外鍵的FooID
和BarID
列上創建):
-- 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%%
是當前存儲行的位置的指示符,因此可能會發生變化。我的直覺是,引擎必須創建以唯一標識一行以實現遊標,事務和併發。
我肯定會選擇1。這是一張關係表,所以在這種情況下,複合PK是完全有意義的。像「複合鍵是邪惡的」通用斷言是...邪惡;) –
@RaphaëlAlthaus我同意這兩個計數...但我正在尋找*證據*,替代品2和3明顯不太理想:) –