我正在创建一个数据库表,但没有为其分配逻辑主键。每个表都应该有一个主键吗?
简短的回答:是的。
长答案:
你需要你的桌子可以加入一些东西
如果您希望您的表被聚集,您需要某种主键。
如果您的表设计不需要主键,请重新考虑您的设计:很可能,您遗漏了一些东西。为什么要保留相同的记录?
在 MySQL 中,如果您没有明确指定主键,InnoDB 存储引擎总是会创建一个主键,从而产生一个您无权访问的额外列。
请注意,主键可以是复合的。
如果您有一个多对多链接表,则在链接中涉及的所有字段上创建主键。因此,您可以确保没有两条或更多条记录描述一个链接。
除了逻辑一致性问题之外,大多数 RDBMS 引擎将受益于将这些字段包含在唯一索引中。
而且由于任何主键都涉及创建唯一索引,因此您应该声明它并获得逻辑一致性和性能。
请参阅我的博客中的这篇文章,了解为什么您应该始终为唯一数据创建唯一索引:
使索引唯一
PS 有一些非常非常特殊的情况,您不需要主键。
大多数情况下,它们包括出于性能原因没有任何索引的日志表。
总是最好有一个主键。这样它会遇到 first normal form 并允许您继续沿 database normalization 路径前进。
正如其他人所说,没有主键有一些原因,但如果有主键,大多数都不会受到伤害
不同意建议的答案。最简洁的答案是不。
主键的目的是唯一标识表上的一行,以便与另一个表形成关系。传统上,自动递增的整数值用于此目的,但对此有一些变化。
但是在某些情况下,例如记录时间序列数据,根本不需要这样的密钥,只会占用内存。使一行独一无二只是......不是必需的!
一个小例子:表 A:LogData
Columns: DateAndTime, UserId, AttribA, AttribB, AttribC etc...
不需要主键。
表 B:用户
Columns: Id, FirstName, LastName etc.
需要主键 (Id) 才能用作 LogData 表的“外键”。
除了极少数情况(可能是多对多关系表,或者临时用于批量加载大量数据的表),我会说:
如果它没有主键,它就不是表!
马克
几乎任何时候我创建了一个没有主键的表,以为我不需要一个,我最终返回并添加了一个。我现在甚至使用自动生成的身份字段创建连接表,我将其用作主键。
加就行了
您是否需要将此表连接到其他表?您需要一种唯一标识记录的方法吗?如果答案是肯定的,您需要一个主键。假设您的数据类似于客户表,其中包含作为客户的人员的姓名。可能没有自然键,因为您需要地址、电子邮件、电话号码等来确定这个 Sally Smith 是否与那个 Sally Smith 不同,并且您将把该信息存储在相关表中,因为这个人可以有多个电话,addesses 、电子邮件等。假设 Sally Smith 与 John Jones 结婚并成为 Sally Jones。如果您的桌子上没有人工钥匙,那么当您更新名称时,您只需将 7 个 Sally Smiths 更改为 Sally Jones,即使其中只有一个结婚并更改了她的名字。当然,在这种情况下,如果没有人工钥匙,你怎么知道哪个 Sally Smith 住在芝加哥,哪个住在洛杉矶?
您说您没有自然密钥,因此您也没有任何字段组合可以使其唯一,这使得人工密钥至关重要。
我发现任何时候我没有自然密钥,人工密钥是维护数据完整性的绝对必要条件。如果您确实有一个自然键,则可以将其用作键字段。但就个人而言,除非自然键是一个字段,否则我还是更喜欢人工键和自然键上的唯一索引。如果你不放一个,你以后会后悔的。
在每张桌子上都有一个 PK 是一个很好的做法,但这不是必须的。很可能您将需要一个唯一索引和/或聚集索引(是否为 PK),具体取决于您的需要。
查看联机丛书中的主键和聚集索引部分(适用于 SQL Server)
“PRIMARY KEY 约束标识具有唯一标识表中行的值的列或列集。表中的任何两行都不能具有相同的主键值。您不能为主键中的任何列输入 NULL。我们建议使用小的整数列作为主键。每个表都应该有一个主键。符合主键值的列或列组合称为候选键。
但也请检查一下:http://www.aisintl.com/case/primary_and_foreign_key.html
为了让它成为未来的证明,你真的应该这样做。如果你想复制它,你需要一个。如果你想把它加入另一张桌子,你的生活(以及明年必须维护它的可怜傻瓜的生活)会容易得多。
聚会迟到了,但我想加两分钱:
每个表都应该有一个主键吗?
如果您在谈论“关系 Albegra”,答案是肯定的。以这种方式对数据建模需要实体和表具有主键。关系代数的问题(除了它有 20 种不同的、不匹配的风格之外),它只存在于纸面上。您无法使用关系代数构建现实世界的应用程序。
现在,如果您正在谈论来自现实世界应用程序的数据库,它们部分/大部分都遵循关系代数,充分利用它并忽略它的其他部分。此外,现在数据库引擎提供了大量的非关系功能(现在是 2020 年)。所以在这种情况下,答案是否定的。无论如何,我 99.9% 的现实世界表都有主键,但也有合理的例外。恰当的例子:事件/日志表(多个索引,但看不到一个键)。
底线是,在遵循实体/关系模型的事务应用程序中,几乎(如果不是)所有表都有主键是很有意义的。如果您决定跳过表的主键,请确保您有充分的理由,并且准备好为您的决定辩护。
我知道为了在 .NET 中使用 gridview 的某些功能,您需要一个主键才能让 gridview 知道哪一行需要更新/删除。一般的做法应该是有一个主键或主键簇。我个人更喜欢前者。
我的职责是维护离岸开发团队创建的应用程序。现在我在应用程序中遇到了各种问题,因为原始数据库模式在某些表上不包含主键。所以请不要因为你糟糕的设计而让其他人受苦。在表上拥有主键总是一个好主意。
我总是有一个主键,即使一开始我还没有考虑到它的目的。有几次我最终需要在一个没有 PK 的表中进行 PK,并且以后再放入它总是比较麻烦。我认为总是包含一个有更多的好处。
如果您使用的是 Hibernate,则无法创建没有主键的实体。如果您使用的是使用普通 sql/ddl 脚本创建的现有数据库,并且没有添加主键,则此问题可能会产生问题
简而言之,没有。但是,您需要记住,某些客户端访问 CRUD 操作需要它。为了将来打样,我倾向于总是使用主键。
我想找到像这样的官方文件 - 15.6.2.1 Clustered and Secondary Indexes - MySQL。
如果 table 没有 PRIMARY KEY 或合适的 UNIQUE 索引,InnoDB 在内部生成一个名为 GEN_CLUST_INDEX 的隐藏聚集索引,该索引包含行 ID 值的合成列。这些行按 InnoDB 分配给此类表中的行的 ID 排序。行 ID 是一个 6 字节的字段,随着新行的插入而单调增加。因此,按行 ID 排序的行在物理上是按插入顺序排列的。
那么,为什么不自己创建主键或类似的东西呢?此外,ORM 无法识别这个隐藏的 ID,这意味着您不能在代码中使用 ID。