2009-04-26 20 views
13

假設您在藝術家和粉絲之間擁有多張桌子。當談到設計的表格,你設計的表像這樣:SQL:您是否需要用於Many-Many表的自動增量主鍵?

ArtistFans 
    ArtistFanID (PK) 
    ArtistID (FK) 
    UserID (FK) 

(ArtistID and UserID will then be contrained with a Unique Constraint 
    to prevent duplicate data) 

還是建立使用複合PK兩個相關領域:

ArtistFans 
    ArtistID (PK) 
    UserID (PK) 

(The need for the separate unique constraint is removed because of the 
compound PK) 

是否有使用前一個模式的任何優點(也許索引?)?

回答

18
ArtistFans 
    ArtistID (PK) 
    UserID (PK) 

即使父表具有它們,使用自動增量PK在這裏也沒有優勢。

我也會在(UserID, ArtistID)上自動創建一個「反向PK」索引:您將需要它,因爲您將通過兩列來查詢表。

自動編號/ ID列有自己的位置。基於物理平臺的標準化過程之後,你會選擇它們來改進某些事情。但不適合鏈接表:如果你的新空房禁地ORM堅持,然後更改奧姆斯...

編輯,2012年10月

要注意,你仍舊需要獨特(UserID, ArtistID)(ArtistID, UserID)指標是非常重要的。添加自動增量僅使用更多不應使用的空間(在內存中,而不僅在磁盤上)

+0

主鍵只是一種特殊類型的索引。重複主鍵的索引只會增加開銷。 – Andomar 2009-04-26 09:24:07

+0

訂單是重要的:這是一個不同的索引 – gbn 2009-04-26 09:42:37

+0

好吧,有道理:) – Andomar 2009-04-26 09:44:04

2

我想不出任何理由使用你列出的第一種形式。複合主鍵很好,並且具有單獨的人造主鍵(以及您在外鍵上需要的唯一約束)只需要更多時間來計算和存儲空間。

1

標準的方法是使用複合主鍵。添加一個單獨的自動增量鍵就是使用你所擁有的東西創建一個已經存在的替代品。正確的數據庫規範化模式會忽視使用自動增量。

5

即使您創建標識列,它也不一定是主鍵。

ArtistFans 
    ArtistFanId 
    ArtistId (PK) 
    UserId (PK) 

標識列可用於將此關係與其他關係聯繫起來。例如,如果創建者表格指定了創建藝術家 - 用戶關係的人員,則它可以在ArtistFanId上具有外鍵,而不是複合ArtistId + UserId主鍵。

另外,標識列是必需的(或者大大改善某些ORM包的操作)。

0

有趣的是所有的答案青睞變種2,所以我必須異議和爭論的變體1)

要回答標題中的問題:不,你不需要它。但是...

中有一個自動增量或標識列,每個表簡化了您的數據模型,以便您知道每個表總是有一個PK列。

因此,從一個表到另一個表的每個關係(外鍵)總是由每個表的單個列組成。此外,如果您碰巧爲表單,列表,報表,日誌等等編寫了一些應用程序框架,您只需要使用單個PK列來處理表格,這簡化了框架的複雜性。

另外,在磁盤空間方面(除了億次記錄以外的表格),額外的id PK列並不會花費太多。

當然,我需要提到一個缺點:在祖父母 - 父母 - 子女關係中,孩子將失去祖父母信息並需要JOIN來檢索它。

5

假設您已經是代理人的關鍵人物(您身處優秀的公司),那麼就需要一路走下去。

有時會被遺忘的一個關鍵點是關係本身可以具有屬性。通常僅僅說明兩件事是相關的是不夠的;你可能不得不描述這種關係的性質。換句話說,關係表沒有什麼特別之處,只能說它只有兩列。

如果這些表沒有什麼特別之處,爲什麼不把它當作其他表使用,並使用代理鍵?如果你最終不得不向表中添加屬性,你會感謝你的幸運表示層,你不必傳遞一個複合鍵來修改這些屬性。

我甚至不會稱之爲經驗法則,更多的是考慮事情。根據我的經驗,一些微不足道的關係最終會攜帶更多的數據,本質上成爲實體,值得代理關鍵。

問題是,事後添加這些鍵可能是一種痛苦。額外的專欄和索引的成本是否值得搶佔這個頭痛的價值,這真的取決於項目。

至於我,一旦被咬傷,兩次害羞 - 我去替代關鍵出門。

0

在我看來,在純SQL ID列是沒有必要的,不應該使用。但對於像Hibernate這樣的ORM框架,使用複合鍵等來管理多對多關係並不簡單,特別是如果連接表有額外的列。

因此,如果我打算在數據庫上使用ORM框架,我寧願將一個自動增量id列添加到該表以及對引用列進行唯一約束。當然,如果需要,也可以使用非空約束。

然後我就像我的項目中的任何其他表一樣對待表。