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

Database design 为什么使用多列作为主键(复合主键),database-design,relational-database,primary-key,ddl,database-table,Database Design,Relational Database,Primary Key,Ddl,Database Table,以这个例子为例 我的理解是,这两列合在一起(p_Id和LastName)表示表Persons的主键。这是正确的吗 为什么有人想使用多列作为主键而不是单个列 给定表中有多少列可以一起用作主键 您的理解是正确的 在很多情况下你都会这样做。一个例子是在关系中,如OrderHeader和OrderDetail。OrderHeader中的主键可能是OrderNumber。OrderDetail中的主键可能是OrderNumber和LineNumber。如果是这两种情况中的任何一种,它就不是唯一的,但这两

以这个例子为例

我的理解是,这两列合在一起(
p_Id
LastName
)表示表
Persons
的主键。这是正确的吗

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

    • 您的理解是正确的

      在很多情况下你都会这样做。一个例子是在关系中,如
      OrderHeader
      OrderDetail
      OrderHeader
      中的主键可能是
      OrderNumber
      OrderDetail
      中的主键可能是
      OrderNumber
      LineNumber
      。如果是这两种情况中的任何一种,它就不是唯一的,但这两种情况的结合保证是唯一的


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

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

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

      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
      
      进一步阅读:或者只需谷歌
      无意义的主键
      ,甚至仔细阅读


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

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

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

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

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

      第二个表格是“字符”——它们的名称和简要说明。主键在“charname”上

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

      您的第二个问题

      给定表中有多少列可以一起用作主键

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

      若您找不到明确的信息,请尝试创建一个测试数据库,以确保能够稳定(和特定)地处理违反限制的情况(这是预期的)。要小心获取关于这一点的正确信息:有时限制是累积的,您将看到不同数据库布局的不同结果


      • [1]
      • [2]
      • [3]

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


      i、 e:如果所有学生证和出生证号码都是唯一分配给一个人的。然后,最好将一个人的主键设置为学生id和出生证号码的组合,因为这样可以防止意外插入两个具有不同学生id和相同出生证的人

      如果我使用branch_id并在两个数据库之间使用复制,这有用吗?这将解决id重复问题?!!请注意,在许多使用生成的主键的情况下,您通常仍然希望复合值上有一个唯一的键。请详细说明“有些人喜欢一种方式,有些人喜欢另一种方式”。请详细说明?不知道该说什么。
      1234     Jobs
      1234     Gates