80

此示例採取的是from w3schools爲什麼使用多列作爲主鍵(複合主鍵)

CREATE TABLE Persons 
(
    P_Id int NOT NULL, 
    LastName varchar(255) NOT NULL, 
    FirstName varchar(255), 
    Address varchar(255), 
    City varchar(255), 
    CONSTRAINT pk_PersonID PRIMARY KEY (P_Id,LastName) 
) 

我的理解的是,無論列組合在一起(P_IdLastName)表示爲表Persons主鍵。它是否正確?

  • 爲什麼有人想使用多列作爲主鍵而不是單列?
  • 可以將多少列一起用作給定表中的主鍵?
+0

...現在也有一個[答案爲2'nd question](http://stackoverflow.com/a/41741054/2932052) – Wolf 2017-01-19 11:58:54

回答

97

你的理解是正確的。

你會在很多情況下做到這一點。一個例子是關係像OrderHeaderOrderDetailOrderHeader中的PK可能是OrderNumberOrderDetail中的PK可能是OrderNumberLineNumber。如果這兩者中的任何一個都不是唯一的,但兩者的組合保證是獨一無二的。

另一種方法是使用生成的(非智能)主鍵,例如在這種情況下使用OrderDetailId。但是,你不會總是很容易地看到這種關係。有些人喜歡一種方式;有些更喜歡另一種方式。

+0

這是有用的,如果我使用branch_id和使用兩個數據庫之間的複製,將解決重複的ids?!! – Mhmd 2014-05-24 06:27:55

+5

請注意,在許多使用生成的主鍵的情況下,您通常仍然需要複合值上的唯一鍵。 – 2016-09-11 12:41:56

2

是的,它們都是主鍵。尤其是在沒有surrogate key的表格中,可能需要指定多個屬性作爲每個記錄的唯一標識符(例如:具有名字和姓氏的表格可能需要它們的組合是唯一的)。

20

複合主鍵的另一個例子是關聯表的使用。假設您有一個人員表格,其中包含一組人員和一個包含一組組的表格。現在你想創建一個關於人和組的多對多關係。意思是每個人都可以屬於許多羣體。以下是使用複合主鍵的表結構。

Create Table Person(
PersonID int Not Null, 
FirstName varchar(50), 
LastName varchar(50), 
Constraint PK_Person PRIMARY KEY (PersonID)) 

Create Table Group (
GroupId int Not Null, 
GroupName varchar(50), 
Constraint PK_Group PRIMARY KEY (GroupId)) 

Create Table GroupMember (
GroupId int Not Null, 
PersonId int Not Null, 
CONSTRAINT FK_GroupMember_Group FOREIGN KEY (GroupId) References Group(GroupId), 
CONSTRAINT FK_GroupMember_Person FOREIGN KEY (PersonId) References Person(PersonId), 
CONSTRAINT PK_GroupMember PRIMARY KEY (GroupId, PersonID)) 
+0

很好的解釋:我認爲m-to-n關係的屬性需要(在規範化的fasion中)是關鍵。 – Wolf 2017-01-19 11:50:19

8

W3Schools的例子不是說什麼時候應該使用複合主鍵,並且只使用相同的例子表作爲其他按鍵被賦予例如語法。

他們選擇的例子可能會通過組合一個無意義的鍵(P_Id)和一個自然鍵(LastName)來誤導你。這種主鍵的奇怪選擇表明,根據模式,以下行是有效的,並且是唯一識別學生的必要條件。直覺上這沒有意義。

1234  Jobs 
1234  Gates 

進一步閱讀:The great primary-key debate或只是谷歌meaningless primary keys甚至細讀此SO question

FWIW - 我的2美分是避免多列主鍵和使用一個單一的生成的ID字段(代理鍵)作爲主鍵並在必要時添加其他(唯一)約束。

2

密鑰中的多個列通常比代理鍵執行得更差。我更喜歡有一個代理鍵,然後是一個多列鍵上的唯一索引。這樣你可以獲得更好的性能,並保持所需的唯一性。更好的是,如果該鍵中的某個值發生更改,則不必在215個子表中更新一百萬個子條目。

2

無論何時您想要確保多個屬性組合的唯一性,都可以使用複合鍵(具有多個屬性的鍵)。一個屬性鍵不會達到同樣的效果。

+1

至於確保一個唯一的密鑰,你可能會依靠兩個屬性的組合來形成一個邏輯上不能重複的密鑰,Person和一個大數據集中的畢業日期就是一個例子。 – 2015-11-08 06:13:21

0

當您在關係數據庫中使用中間表時,在多個表上使用主鍵會派上用場。

我將使用我曾經爲一個示例創建的數據庫,特別是該表中的三個表。 I cre ä在幾年前建立了一個網絡數據庫。一張桌子被稱爲「漫畫」—所有漫畫,其標題,圖像文件名等的列表。主鍵是「漫畫」。

第二張表是「人物」—他們的名字和一個簡短的描述。主鍵在「charname」上。

由於每個漫畫—有一些例外—有多個字符,每個字符出現多個漫畫中,這是不切實際的把列在任一「字」或「漫畫」,以反映這一點。相反,我創建了ä ted a 第三個表被稱爲「漫畫家」,這是一個列表,其中的漫畫出現了哪些人物。由於該表基本上加入了兩個表,因此它只需要兩列:charname和comicnum,並且主鍵在兩個列上。

2

你第二部分的問題

多少列可以一起在一個給定表的主鍵使用嗎?

是特定實現:它是在實際使用的DBMS中定義的。 [1],[2],[3]您必須檢查您使用的數據庫系統的技術規格。有些非常詳細,有些則不是。在網上搜索這種限制可能很難,因爲術語各不相同。術語複合主鍵應當是強制性的;)

如果你不能找到明確的信息,有一個測試數據庫儘量保證你可以期待違反穩定(與特定的)處理的限制(這是合理的期望)。請小心獲取有關此信息的正確信息:有時會限制積累,並且您將看到不同數據庫佈局的不同結果。