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

roc*_*ala 102 ddl database-design primary-key relational-database database-table

这个例子来自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)
)
Run Code Online (Sandbox Code Playgroud)

我的理解是两个列在一起(P_IdLastName)代表表的主键Persons.它是否正确?

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

MJB*_*MJB 112

你的理解是正确的.

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

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

  • 请注意,在许多使用生成的主键的情况下,您通常仍希望在复合值上使用唯一键. (11认同)
  • 如果我使用branch_id并在两个数据库之间使用复制,这会有用吗?!! (2认同)
  • 请详细说明一下?不知道该说些什么。我认识一些人更喜欢将多个串联字段作为键,因为这样更容易直观地理解他们正在查看的内容。我认识其他人,他们更喜欢为每一行分配一个唯一的键,因为这样打字更容易、更快。这就是你问的吗? (2认同)

Joh*_*ock 25

复合主键的另一个示例是关联表的使用.假设您有一个包含一组人员的人员表和一个包含一组组的组表.现在,您希望在人员和组上创建多对多关系.意味着每个人都可以属于许多群体.以下是使用复合主键的表结构.

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))
Run Code Online (Sandbox Code Playgroud)


Rob*_*son 9

W3Schools示例并未说明何时应使用复合主键,并且仅使用与其他键相同的示例表来提供示例语法.

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

1234     Jobs
1234     Gates
Run Code Online (Sandbox Code Playgroud)

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

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

  • “伟大的主键辩论”并不愚蠢。对于不是 sql 开发人员或 sql DBA 并且没有将所有时间都花在 sql 上的开发人员来说,这是一个非常有效的问题。即使在纯 sql 中,我也宁愿在加入时将一个无意义的自动生成的键作为主键,而不必记住传递 n 位数据作为自然键。欢迎您提出您的观点,但我们希望您不要这么轻视。 (2认同)