121

此示例取自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。这个对吗?

  • 为什么有人要使用多列而不是单列作为主键?
  • 在给定表中可以将多少列一起用作主键?
4

9 回答 9

128

你的理解是正确的。

在很多情况下你会这样做。一个例子是和 之间的OrderHeader关系OrderDetail。中的PKOrderHeader可能是OrderNumber。中的 PKOrderDetail可能是OrderNumberAND LineNumber。如果是这两者中的任何一个,它就不会是唯一的,但两者的组合保证是唯一的。

另一种方法是使用生成的(非智能)主键,例如在这种情况下OrderDetailId。但是你不会总是那么容易地看到这种关系。有些人喜欢一种方式;有些人更喜欢另一种方式。

于 2010-04-12T23:53:55.860 回答
29

复合主键的另一个例子是关联表的使用。假设您有一个包含一组人员的人员表和一个包含一组组的组表。现在您想在人和组上创建多对多关系。这意味着每个人都可以属于许多组。这是使用复合主键的表结构的样子。

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))
于 2010-04-13T00:11:47.147 回答
10

W3Schools 示例并没有说明何时应该使用复合主键,只是给出了使用与其他键相同的示例表的示例语法。

他们选择的示例可能会通过组合无意义的键 (P_Id) 和自然键 (LastName) 来误导您。这种奇怪的主键选择表明以下行根据架构是有效的,并且是唯一标识学生所必需的。直觉上这是没有意义的。

1234     Jobs
1234     Gates

进一步阅读:伟大的主键辩论或只是谷歌meaningless primary keys,甚至仔细阅读这个SO 问题

FWIW - 我的 2 美分是避免多列主键并使用单个生成的 id 字段(代理键)作为主键,并在必要时添加额外的(唯一)约束。

于 2010-04-14T22:33:14.437 回答
4

只要您想确保多个属性组合的唯一性,就可以使用复合键(具有多个属性的键)。单个属性键不会达到同样的效果。

于 2010-11-23T14:09:09.837 回答
3

通常,键中的多个列的性能比代理键差。我更喜欢有一个代理键,然后是一个多列键上的唯一索引。这样,您可以获得更好的性能并保持所需的唯一性。更好的是,当该键中的一个值发生更改时,您也不必更新 215 个子表中的一百万个子条目。

于 2010-11-22T20:16:01.867 回答
3

是的,它们都构成了主键。尤其是在没有代理键的表中,可能需要指定多个属性作为每条记录的唯一标识符(不好的示例:同时具有名字和姓氏的表可能需要将它们组合为独特的)。

于 2010-04-12T23:54:56.980 回答
3

你的第二个问题

在给定表中可以将多少列一起用作主键?

是特定于实现的:它是在实际使用的 DBMS 中定义的。[1],[2],[3]您必须检查您使用的数据库系统的技术规范。有些非常详细,有些则不然。在网络上搜索这些限制可能很困难,因为术语会有所不同。术语复合主键应该是强制性的;)

如果您找不到明确的信息,请尝试创建一个测试数据库以确保您可以预期对限制违规(这是预期的)进行稳定(和具体)的处理。小心获取有关此的正确信息:有时限制是累积的,您会看到不同数据库布局的不同结果。


于 2017-01-19T11:47:28.053 回答
2

当您在关系数据库中使用中间表时,在多个表上使用主键会派上用场。

我将使用我曾经制作的数据库作为示例,特别是该表中的三个表。几年前,我为网络漫画创建了一个数据库。一个表被称为“comics”——所有漫画的列表、它们的标题、图像文件名等。主键是“comicnum”。

第二个表是“字符”——他们的名字和简短的描述。主键在“charname”上。

由于每部漫画(除了一些例外)都有多个角色,并且每个角色都出现在多部漫画中,因此在“角色”或“漫画”中放置一列来反映这一点是不切实际的。相反,我创建了第三个表,称为“comicchars”,它列出了哪些角色出现在哪些漫画中。由于该表本质上连接了两个表,因此它只需要两列:charname 和comicnum,并且主键在两者上。

于 2016-09-11T12:02:55.553 回答
1

我们创建复合主键来保证组成单个记录的列值的唯一性。这是一个约束,有助于防止插入不应重复的数据。

即:如果所有学生证和出生证明号码都唯一分配给一个人。那么最好将一个人的主键设置为学生 ID 和出生证明号码的组合,因为这样可以防止您意外插入两个具有不同学生 ID 和相同出生证明的人。

于 2019-08-08T20:14:39.133 回答