每个表都应该有一个主键吗?

Dan*_*ira 319 database database-design

我正在创建一个数据库表,并且没有为其分配逻辑主键.所以,我正考虑在没有主键的情况下离开它,但我对此感到有点内疚.我是不是该?

每个表都应该有一个主键吗?

Qua*_*noi 295

简短回答:是的.

答案很长:

  • 你需要你的桌子可以加入某些东西
  • 如果您希望将表集群化,则需要某种主键.
  • 如果您的表设计不需要主键,请重新考虑您的设计:最有可能的是,您遗失了一些东西.为何保留相同的记录?

在MySQL中,如果您没有明确指定它,InnoDB存储引擎总是会创建一个主键,从而创建一个您无权访问的额外列.

请注意,主键可以是复合键.

如果您有多对多链接表,则在链接中涉及的所有字段上创建主键.因此,您可以确保没有两条或更多条描述一条链接的记录.

除了逻辑一致性问题之外,大多数RDBMS引擎都将受益于将这些字段包含在唯一索引中.

由于任何主键都涉及创建唯一索引,因此您应该声明它并获得逻辑一致性和性能.

请参阅我的博客中的这篇文章,了解为什么您应该始终为唯一数据创建唯一索引:

PS有一些非常非常特殊的情况,您不需要主键.

它们主要包括由于性能原因而没有任何索引的日志表.

  • 只是评论修辞问题"为什么保持相同的记录?".请注意,仅添加PK不会确保没有重复.通常PK对用户不可见,因此重要的是在可见字段中,其可能包含重复数据.根据您的设计,这可能是合乎需要的. (3认同)
  • @annakata:他们应该有一个复合主键 (2认同)
  • 键与可连接性无关。集群参数取决于您使用的 DBMS,并混合了逻辑和物理考虑。 (2认同)

Mic*_*ler 34

总是最好有一把主键.这样,它符合第一范式,并允许您继续沿数据库规范化路径.

正如其他人所说,有一些原因没有主键,但如果有主键,大多数都不会受到伤害

  • @PaulSuart数据不必总是处于正常形式.事实上,当数据变得庞大时,它不应该保持正常形式,否则访问数据对于进行表连接的查询来说会非常慢.正常形式是一种"理想化",实际上只有在数据不会增长的情况下才有可能实现巨大. (4认同)

mar*_*c_s 13

除了一些非常罕见的情况(可能是多对多关系表,或临时用于批量加载大量数据的表),我会说:

如果没有主键,则不是表格!

  • 严格来说,这句话是错误的.表可以是查询语言创建的"查看表".RDBMS由关系而不是表组成.那句话应该说:"如果它没有主键,那就不是关系!". (9认同)

The*_*hos 13

不同意建议的答案。简短的回答是:

主键的目的是唯一标识表上的一行,以便与另一个表形成关系。传统上,自动递增的整数值用于此目的,但也有变化。

但是,在某些情况下,例如记录时间序列数据,根本不需要这样的键的存在,只需要占用内存。使行唯一只是...不是必需的!

一个小例子:表A:LogData

Columns:  DateAndTime, UserId, AttribA, AttribB, AttribC etc...
Run Code Online (Sandbox Code Playgroud)

不需要主键。

表 B:用户

Columns: Id, FirstName, LastName etc. 
Run Code Online (Sandbox Code Playgroud)

需要主键 (Id) 才能用作 LogData 表的“外键”。

  • 简短的回答是绝对“是”。长的答案是“不”。就像有人问“我必须有驾照才能开车吗?” 从技术上讲,答案是否定的,但如果他们问这个问题,那么我们其他人肯定希望他们有一个。同样,如果 OP 询问“我应该使用 PK 吗?” 那么答案绝对是“是”,因为他们不太可能理解他们不应该理解的细微差别。最好还是拥有它们。 (2认同)

tva*_*son 12

几乎任何时候我都创建了一个没有主键的表,以为我不需要一个,我最后回去添加一个.我现在甚至使用自动生成的标识字段创建连接表,我将其用作主键.

  • 连接表是一个主键 - 一个复合键,由两个连接的记录的PK组成.例如CREATE TABLE PersonOrder(PersonId int,OrderId int,PRIMARY KEY(PersonId,OrderId)). (11认同)
  • 是的,但如果链接表还有第三个属性,请说"OrderDate".你会将它添加到复合键吗?恕我直言 - 因为它是进一步可缩减的,并且不提供主键应具有的不可缩减的特征. (3认同)

HLG*_*GEM 8

你是否需要将此表加入其他表?您是否需要一种唯一识别记录的方法?如果答案是肯定的,那么您需要一个主键.假设您的数据类似于客户表,其中包含客户的名称.可能没有自然键,因为您需要地址,电子邮件,电话号码等来确定这个Sally Smith是否与Sally Smith不同,并且您将该信息存储在相关表格中,因为此人可以拥有多个手机,addesses假设莎莉史密斯与约翰琼斯结婚并成为莎莉琼斯.如果您在桌面上没有人工钥匙,当您更新名称时,您只需将7 Sally Smiths更改为Sally Jones,即使其中只有一人结婚并更改了姓名.当然,在这种情况下,如果没有人工关键,你怎么知道哪个莎莉史密斯住在芝加哥,哪个住在洛杉矶?

你说你没有自然键,因此你没有任何字段组合来制作独特的,这使得人工关键变得至关重要.

我发现任何时候我都没有自然键,人工键是保持数据完整性的绝对必要条件.如果您有自然键,则可以将其用作关键字段.但个人除非自然键是一个字段,否则我仍然更喜欢自然键上的人工键和唯一索引.如果你没有放入,你会后悔的.


rap*_*aëλ 7

只需添加它,稍后当你没有时,你会感到抱歉(选择,删除.链接等)


end*_*o64 6

在每张桌子上都有一个PK是一个好习惯,但它不是必须的.根据您的需要,您可能需要一个唯一索引和/或聚簇索引(或者不是PK).

查看联机丛书中的主键和聚簇索引部分(适用于SQL Server)

" PRIMARY KEY约束标识具有唯一标识表中行的值的列或列集.表中没有两行可以具有相同的主键值.您不能为主键中的任何列输入NULL.我们建议使用一个小的,整数列作为主键,每个表都应有一个主密钥.有资格作为主键值被称为候选键列的列或组合. "

但是请检查一下:http://www.aisintl.com/case/primary_and_foreign_key.html

  • 该页面非常愚蠢.首先,出于性能原因需要主键.通过阅读他的页面,我了解到在书桌上添加ID是没用的,因为书的文字是独一无二的; 显然,这个人从未使用过数据库.但是他在理解批评的内容方面也存在问题.写入的页面1)PK值引用行2)您可以通过任何列连接2个表.没有矛盾.令人惊讶的是,一篇学术文章作者并不了解关系理论的基本原理. (4认同)

The*_*ler 5

聚会迟到了,但我想补充两点:

每个表都应该有主键吗?

  • 如果你谈论的是“关系阿尔贝格拉”,答案是肯定的。以这种方式建模数据需要实体和表具有主键。关系代数的问题(除了它有大约 20 种不同的、不匹配的风格这一事实之外)是它只存在于纸面上。您无法使用关系代数构建现实世界的应用程序。

  • 现在,如果您谈论来自现实世界应用程序的数据库,它们部分/大部分遵循关系代数,充分利用它并忽略它的其他部分。此外,如今数据库引擎提供了大量的非关系功能(现在是 2020 年)。所以在这种情况下答案是否定的。无论如何,我的现实世界中 99.9% 的表都有主键,但也有合理的例外。典型的例子:事件/日志表(多个索引,但看不到单个键)。

底线是,在遵循实体/关系模型的事务应用程序中,为几乎(如果不是)所有表拥有主键是很有意义的。如果您决定跳过表的主键,请确保您有充分的理由,并且准备好捍卫您的决定。