为什么使用多列作为主键(复合主键)

这个例子取自 W3学校的

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的主键。是这样吗?

  • 为什么有人想要使用多列作为主键而不是单列?
  • 在给定的表中,有多少列可以作为主键一起使用?
186741 次浏览

你的理解是正确的。

You would do this in many cases. One example is in a relationship like OrderHeader and OrderDetail. The PK in OrderHeader might be OrderNumber. The PK in OrderDetail might be OrderNumber AND LineNumber. If it was either of those two, it would not be unique, but the combination of the two is guaranteed unique.

另一种方法是使用生成的(非智能的)主键,例如在本例中使用 OrderDetailId。但那样的话,你就不会总是轻易地看到这种关系。有些人喜欢一种方式,有些人喜欢另一种方式。

是的,它们都是主键。特别是在没有 代理密钥的表格中,可能需要为每条记录指定多个属性作为唯一标识符(坏的例子: 一个同时有名和姓的表格可能要求它们的组合是唯一的)。

Another example of compound primary keys are the usage of Association tables. Suppose you have a person table that contains a set of people and a group table that contains a set of groups. Now you want to create a many to many relationship on person and group. Meaning each person can belong to many groups. Here is what the table structure would look like using a compound primary key.

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))

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

他们选择的示例可能会通过组合一个无意义的键(P _ Id)和一个自然键(LastName)来误导您。这个奇怪的主键选择表明,根据模式,以下行是有效的,并且是唯一标识学生所必需的。从直觉上讲,这说不通。

1234     Jobs
1234     Gates

Further Reading: 伟大的主键辩论 or just Google meaningless primary keys or even peruse this 有个问题

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

一般来说,一个键中的多个列的性能会比代理键更差。我倾向于使用代理键,然后在多列键上使用唯一索引。这样,您就可以获得更好的性能,并保持所需的唯一性。更妙的是,当该键中的一个值发生更改时,您不必更新215个子表中的100万个子条目。

只要希望确保多个属性组合的唯一性,就可以使用复合键(具有多个属性的键)。单个属性键不会实现同样的功能。

当你在一个关系数据库中使用一个中间表时,在多个表上使用一个主键非常方便。

我将使用我曾经创建的一个数据库作为示例,特别是该表中的三个表。几年前我为一个网络漫画创建了一个数据库。其中一个表格叫做“ comics”,它列出了所有的漫画,它们的标题,图片文件名等等。主要关键词是“ comicnum”。

第二个表是“字符”,它们的名称和一个简短的描述。主键在“ charname”上。

由于每个漫画(除了一些例外)都有多个角色,而且每个角色都出现在多个漫画中,因此在“角色”或“漫画”中设置一个专栏来反映这一点是不切实际的。相反,我 cre & auml; ted 一个 第三表被称为“ comicchars”,这是一个包含哪些角色出现在哪些漫画中的列表。由于这个表实际上连接了两个表,所以它只需要两列: charname 和 comicnum,并且两个表上都有主键。

你的第二个问题

How many columns can be used together as a primary key in a given table?

is implementation specific: it's defined in the actual DBMS being used.[1] ,[2] ,[3] You have to inspect the technical specification of the database system you use. Some are very detailed, some are not. Searching the web about such limitations can be hard because the terminology varies. The term 复合主键 should be mandatory ;)

如果您找不到明确的信息,那么尝试创建一个测试数据库,以确保您可以预期对违反限制(这是预期的)的稳定(和特定)处理。要注意获得关于这一点的正确信息: 有时候这些限制是累积起来的,您将看到不同数据库布局的不同结果。


  • [1] < a href = “ https://stackoverflow. com/questions/16966765/Composite-main-key-limit”> sql-Composite main key limit?-Stack Overflow
  • [2] < a href = “ http://www.c-sharker.com/blogs/SQL-Server-Max-column-per-basic-key1”rel = “ nofollow noReferrer”> SQL Server-Max column per main key
  • 在 Oracle 9i 和10g 中,一个表中的主键可以包含多少个最大列?

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

例如: 如果所有的学生证和出生证明号码被唯一地分配给一个人。那么将一个人的主键设置为由学生证和出生证号组成的组合是一个好主意,因为这样可以防止意外地插入两个拥有不同学生证和相同出生证的人。