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]您必须检查您使用的数据库系统的技术规格。有些非常详细,有些则不是。在网上搜索这种限制可能很难,因为术语各不相同。术语复合主键应当是强制性的;)

如果你不能找到明确的信息,有一个测试数据库尽量保证你可以期待违反稳定(与特定的)处理的限制(这是合理的期望)。请小心获取有关此信息的正确信息:有时会限制积累,并且您将看到不同数据库布局的不同结果。