我的数据库表中是否应该始终有一个主键?
让我们采用 SO 标记。您可以在任何修订中看到标签,它可能位于带有 postID 和修订号的 tag_rev 表中。我需要为此进行PK吗?
另外,由于它在 rev 表中并且当前未使用标签应该是 tagID 的 blob,而不是多个 post_id tagid 对的多个条目?
我的数据库表中是否应该始终有一个主键?
让我们采用 SO 标记。您可以在任何修订中看到标签,它可能位于带有 postID 和修订号的 tag_rev 表中。我需要为此进行PK吗?
另外,由于它在 rev 表中并且当前未使用标签应该是 tagID 的 blob,而不是多个 post_id tagid 对的多个条目?
一个表应该有一个主键,以便您可以用它唯一地标识每一行。
从技术上讲,您可以拥有没有主键的表,但您将违反良好的数据库设计规则。
您应该努力在您可能希望通过该键访问(或更新或删除)单个记录的任何重要表中拥有一个主键。主键可以由多列组成,正式地说,将是最短的可用超键;即,最短的可用列组,它们一起唯一标识任何行。
我不知道 Stack Overflow 数据库架构是什么样的(从我在 Jeff 的博客上读到的一些内容来看,我不想知道),但在你描述的情况下,完全有可能存在一个主要的跨帖子标识符、修订号和标签值的键;当然,这将是可用的最短(也是唯一)超级密钥。
关于您的第二点,虽然支持在存档表中聚合值可能是合理的,但它确实违反了表中每个行/列交集应该包含一个值的原则。虽然它可能会稍微简化开发,但没有理由不能使用带有版本化元数据的规范化表,即使对于像标签这样微不足道的东西也是如此。
我倾向于同意大多数表应该有一个主键。我只能想到两次这样做没有意义。
基本上,如果您正在编写一个可能需要在外键关系中引用的表,那么主键很重要,如果您不能肯定它不会是,那么只需添加 PK。:)
从 MySQL 5.5 参考手册第13.1.17节:
如果您没有 PRIMARY KEY 并且应用程序要求您的表中的 PRIMARY KEY,则 MySQL 返回第一个没有 NULL 列的唯一索引作为 PRIMARY KEY。
所以,从技术上讲,答案是否定的。但是,正如其他人所说,在大多数情况下它非常有用。
我坚信每张表都应该有一种方法来唯一地标识一条记录。对于 99% 的表,这是主键。其余的你可能会得到一个唯一的索引(我在想一列在这里查找类型表)。每当我不得不使用无法唯一标识记录的表时,就会遇到麻烦。
我还相信,如果您使用代理键作为您的 PK,那么您应该尽可能在构成自然键的任何字段组合上拥有一个单独的唯一索引。我意识到有太多时候你没有真正的自然键(名称不是唯一的,或者使某些独特的东西可能分布在几个父子表中),但如果你有一个,请确保它具有唯一索引或创建为 PK。
如果没有PK,你将如何更新或删除单行?这是不可能的!老实说,我使用过几次没有 PK 的表,例如存储活动日志,但即使在这种情况下,也建议使用一个,因为时间戳不够精细。临时表是另一个例子。但是根据关系理论,PK是强制性的。
有钥匙和关系很好。有很大帮助。但是,如果您的应用程序足以处理关系,那么您可能会跳过键(尽管我建议您拥有它们)
由于我使用 Subsonic,我总是为我的所有表创建一个主键。许多数据库抽象库需要一个主键才能工作。
注意:这并不能回答您问题的“大统一理论”基调,但我只是说在实践中,有时您必须为每个表创建一个主键。
如果它是一个连接表,那么我不会说你需要一个主键。例如,假设您有表 PERSONS、SICKPEOPLE 和 ILLNESSES。ILLNESSES 表有流感、感冒等,每个都有一个主键。PERSONS 有关于人的常用资料,每个资料也有一个主键。SICKPEOPLE 表中只有生病的人,它有两列,PERSONID 和 ILLNESSID,外键返回各自的表,没有主键。PERSONS 和 ILLNESSES 表包含实体,实体获取主键。SICKPEOPLE 表中的条目不是实体,也没有主键。
数据库本身没有键,但它们的组成表可能。我想你的意思是,但以防万一......
无论如何,具有大量行的表绝对应该有主键;只有几行的表不一定需要它们,尽管它们不会受到伤害。这取决于表的用途和大小。纯粹主义者会将主键放在每个表中。这没有错;在小桌子上也没有省略 PK。
编辑添加了一个指向我关于这个问题的博客条目的链接,其中我讨论了一个数据库管理人员认为没有必要在特定表中包含主键的情况。我认为这充分说明了我的观点。