首页 文章

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

提问于
浏览
92

这个例子是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 的主键 . 它是否正确?

  • 为什么有人想要使用多列作为主键而不是单列?

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

8 回答

  • 2

    是的,它们都是主键 . 特别是在没有surrogate key的表中,可能需要指定多个属性作为每个记录的唯一标识符(错误示例:具有名字和姓氏的表可能需要它们的组合是唯一的) .

  • 0

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

  • 10

    你的理解是正确的 .

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

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

  • 104

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

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

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

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

    1234     Jobs
    1234     Gates
    

    进一步阅读:The great primary-key debate或只是谷歌 meaningless primary keys 或甚至仔细阅读SO question

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

  • 2

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

  • 22

    你的第二部分问题

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

    是特定于实现的:它在实际使用的DBMS中定义 . [1],[2],[3]您必须检查您使用的数据库系统的技术规范 . 有些非常详细,有些则不是 . 在网上搜索这种限制可能很难,因为术语各不相同 . 应强制使用 composite primary key 这一术语;)

    如果您找不到显式信息,请尝试使用测试数据库,以确保您可以期望稳定(和特定)处理违规限制(合理预期) . 小心获取有关此信息的正确信息:有时会累积限制,并且您将看到不同数据库布局的不同结果 .


  • 2

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

    我将使用我曾经为一个例子制作的数据库,特别是该表中的三个表 . 几年前,我为一个webcomic创建了一个数据库 . 一张 table 被称为“漫画” - 所有漫画,其 Headers ,图像文件名等的列表 . 主要键是“comicnum” .

    第二个表是“人物” - 他们的名字和简要说明 . 主键是打开的“CHARNAME” .

    由于每个漫画 - 有一些例外 - 有多个角色,每个角色出现在多个漫画中,因此将列放在"characters"或"comics"中以反映这一点是不切实际的 . 相反,我创建了第三个名为"comicchars"的表,这是一个列表,其中出现了漫画中出现的角色 . 由于这个表基本上加入了两个表,它只需要两列:charname和comicnum,主键同时存在 .

相关问题