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

时间:2009-05-08 14:49:15

标签: database database-design

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

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

16 个答案:

答案 0 :(得分:285)

简短回答:

答案很长:

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

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

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

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

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

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

在我的博客中查看此文章,了解为何应始终为唯一数据创建唯一索引:

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

大多数情况下,它们包含因性能原因而没有任何索引的日志表。

答案 1 :(得分:31)

总是最好拥有主键。这样,它符合first normal form并允许您继续database normalization路径。

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

答案 2 :(得分:13)

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

  
    

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

  

马克

答案 3 :(得分:12)

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

答案 4 :(得分:7)

只需添加它,稍后当您没有(选择,删除,链接等)

时,您会感到抱歉

答案 5 :(得分:7)

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

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

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

答案 6 :(得分:6)

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

查看联机丛书(适用于SQL Server)

上的主键和聚簇索引部分

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

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

答案 7 :(得分:3)

我知道为了在.NET中使用gridview的某些功能,您需要一个主键,以便gridview知道哪一行需要更新/删除。一般做法应该是拥有主键或主键群集。我个人更喜欢前者。

答案 8 :(得分:2)

我总是有一把主键,即使在开始时我还没有考虑到它的目的。曾经有几次我最终需要一个没有一个PK的表格中的PK,以后再把它放进去总是比较麻烦。我认为总是包括一个更多的好处。

答案 9 :(得分:2)

为了让未来证明你真的应该。如果你想复制它,你需要一个。如果你想把它加入到另一张桌子上,那么你的生活(以及那些必须在明年维持它的傻瓜)将会变得如此简单。

答案 10 :(得分:1)

简而言之,没有。但是,您需要记住某些客户端访问CRUD操作需要它。为了将来打样,我倾向于总是使用主键。

答案 11 :(得分:1)

如果您正在使用Hibernate,则无法在没有主键的情况下创建实体。如果您正在使用使用普通sql / ddl脚本创建的现有数据库并且未添加主键,则此问题可能会产生问题

答案 12 :(得分:1)

我负责维护离岸开发团队创建的应用程序。现在我在应用程序中遇到各种问题,因为原始数据库模式在某些表上不包含PRIMARY KEYS。所以请不要让其他人因为你糟糕的设计而受苦。在表格上使用主键始终是个好主意。

答案 13 :(得分:1)

晚了聚会,但我想加两分钱:

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

  • 如果您在谈论“关系Albegra”,答案是。通过这种方式对数据建模需要实体和表具有主键。关系代数的问题(除了事实之外,它还有20种不同的,错配的味道)是它仅存在于纸张中。您不能使用关系代数构建现实世界的应用程序。

  • 现在,如果您谈论的是来自真实世界应用程序的数据库,则它们会充分利用并最好地丢弃其余部分,从而部分/大部分遵循关系代数。此外,如今数据库引擎提供了巨大的非关系功能(现在是2020年)。因此,在这种情况下,答案是。无论如何,我的真实世界表中有99.9%具有主键,但是有合理的例外。例子:事件/日志表(多个索引,但看不到单个键)。

最重要的是,在遵循实体/关系模型的事务应用程序中,对于几乎所有(如果不是所有)表都具有主键是很有意义的。如果您决定跳过表的主键,请确保有充分的理由,并且准备捍卫自己的决定。

答案 14 :(得分:0)

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

主键的目的是唯一地标识表上的一行,以便与另一个表建立关系。传统上,将自动递增的整数值用于此目的,但是对此有所不同。

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

一个小例子: 表格A:LogData

Columns:  DateAndTime, UserId, AttribA, AttribB, AttribC etc...

不需要主键。

表B:用户

Columns: Id, FirstName, LastName etc. 

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

答案 15 :(得分:0)

我想找到类似这样的官方信息 - 15.6.2.1 Clustered and Secondary Indexes - MySQL

<块引用>

如果表没有 PRIMARY KEY 或合适的 UNIQUE 索引,InnoDB 会在包含行 ID 值的合成列上内部生成一个名为 GEN_CLUST_INDEX 的隐藏聚集索引。行按 InnoDB 分配给此类表中行的 ID 排序。行 ID 是一个 6 字节的字段,随着插入新行而单调增加。因此,按行 ID 排序的行在物理上是按插入顺序排列的。

那么,为什么不自己创建主键或类似的东西呢?此外,ORM 无法识别此隐藏 ID,这意味着您无法在代码中使用 ID。