【问题标题】:Should a database table always have primary keys?数据库表是否应该始终具有主键?
【发布时间】:2010-10-24 07:54:03
【问题描述】:

我的数据库表中是否应该始终有一个主键?

让我们使用 SO 标记。您可以在任何修订中看到标签,它可能位于带有 postID 和修订号的 tag_rev 表中。我需要为此进行PK吗?

另外,因为它在一个 rev 表中并且当前不使用标签应该是一个 tagID 的 blob,而不是多个 post_id tagid 对的多个条目?

【问题讨论】:

标签: database primary-key modeling


【解决方案1】:

应该有一个主键,以便您可以用它唯一地标识每一行。

从技术上讲,您可以拥有没有主键的表,但您将违反良好的数据库设计规则。

【讨论】:

  • 在一个遗留应用程序中,我维护有几个表,每个表只有一行,这是设计的。还有一些不超过十行的表(一种或另一种查找)。在这种情况下完全没有主键的意义。至少在我看来,无论如何。
  • @Cyber​​herbalist:即使在这种情况下,如果您以编程方式使用该表,您可能需要一种方法来分别识别每一行。另请注意,拥有主键并不意味着拥有单独的主键。您可能将列组合作为主键。顺便说一句,当您认为模式和规则在您的特定情况下没有意义时,跳过它们是完全有效的,但在绝大多数情况下,没有主键会造成伤害。
  • 没错。当我阅读我们(英国)中学的 MS Access 的“数据库”小册子时,我想到了 WTF。引用 - “如果 Access 要求您定义主键,请单击否。”
  • @Mehrdad:我同意,一般来说。在我提到的情况下,对于小型多行表,总是有一些列用作事实上的键,即使它没有被定义为 PK。以编程方式访问这些查找似乎不会影响应用程序的操作。对于少数单行表来说,任何类型的键都没有意义。 @person-b:我也想WTF!
  • Cyber​​herbalist:小表被另一个表引用的情况,你不想要一个主键吗? (用作外键)。
【解决方案2】:

您应该努力在您可能希望通过该键访问(或更新或删除)单个记录的任何重要表中拥有一个主键。主键可以由多个列组成,正式地说,将是最短的可用超键;即最短的可用列组,它们一起唯一标识任何行。

我不知道 Stack Overflow 数据库架构是什么样的(根据我在 Jeff 的博客上读到的一些内容,我不想知道),但在您描述的情况下,完全有可能是跨帖子标识符、修订号和标签值的主键;当然,这将是可用的最短(也是唯一)超级密钥。

关于您的第二点,虽然支持在存档表中聚合值可能是合理的,但它确实违反了表中每个行/列交叉点应包含一个值的原则。虽然它可能会稍微简化开发,但没有理由不能使用带有版本化元数据的规范化表,即使对于像标签这样微不足道的东西也是如此。

【讨论】:

    【解决方案3】:

    我倾向于同意大多数表都应该有一个主键。我只能想到两次这样做没有意义。

    1. 如果您有一个将键与其他键相关联的表。例如,要将 user_id 与 answer_id 关联起来,该表不需要主键。
    2. 一个日志记录表,其唯一真正目的是创建审计跟踪。

    基本上,如果您正在编写一个可能需要在外键关系中引用的表,那么主键很重要,如果您不能肯定它不会,那么只需添加 PK。 :)

    【讨论】:

    • 在第 1 点,您应该有一个复合主键 (user_id,answer_id)。在第 2 点上,我希望有一个时间戳列,但如果有可能有两个相同的行(相同的时间戳和消息),我肯定想知道某事已经发生了两次,并且能够分别处理这些事件。 “13:15-双倍透支”与“533-13:15-双倍透支,534-13:15-双倍透支”有很大不同。
    • @Draemon - 如果你的表中有两列,那么拥有一个复合键就太过分了,IMO,因为你真的没有得到任何好处。如果您可以同时发生两个事件,那么您将遇到更大的问题,如果您不希望在同一记录上同时进行两个更新。
    【解决方案4】:

    请参阅有关是否需要 整数 主键的相关问题。其中一个答案以打标签为例:

    Are there any good reasons to have a database table without an integer primary key

    有关标记和键的更多讨论,请参阅以下问题:

    Id for tags in tag systems

    【讨论】:

    • 然而,这不是问题所在。 @acidzombie 不是询问非整数 PK,而是询问是否具有任何类型的主键(即字符串)的一般情况。
    【解决方案5】:

    来自 MySQL 5.5 参考手册部分13.1.17

    如果您没有 PRIMARY KEY 并且应用程序要求您的表中的 PRIMARY KEY,MySQL 将返回第一个没有 NULL 列的唯一索引作为 PRIMARY KEY。

    所以,从技术上讲,答案是否定的。但是,正如其他人所说,在大多数情况下它非常有用。

    【讨论】:

    • 没有人提到的是主键可以是多列,这就是我现在所做的
    • Rob 确实提到了它。也许您应该将his answer 标记为已接受?
    • 嘿,他做到了...也许我想等到我尝试过而忘记接受它。这是一个赞成票
    【解决方案6】:

    我坚信每张表都应该有一种方法来唯一标识一条记录。对于 99% 的表,这是主键。对于其余部分,您可能会使用唯一索引(我在想一列在这里查找类型表)。每当我不得不使用无法唯一标识记录的表时,就会遇到麻烦。

    我还相信,如果您使用代理键作为您的 PK,那么您应该尽可能在构成自然键的任何字段组合上使用单独的唯一索引。我意识到有太多次你没有真正的自然键(名称不是唯一的,或者使某些独特的东西可能分布在几个父子表中),但如果你有一个,请确保它具有唯一索引或被创建为 PK。

    【讨论】:

      【解决方案7】:

      如果没有PK,你将如何更新或删除单行?这是不可能的!老实说,我使用过几次没有 PK 的表,例如存储活动日志,但即使在这种情况下,也建议使用一个,因为时间戳不够精细。临时表是另一个例子。但根据关系理论,PK是强制性的。

      【讨论】:

      • 不可能?不。小表中的行可以在没有 PK 的情况下唯一标识。如果它是一个小型查找表(我看到最常用的无 PK 表),总有一个值可能是关键,但无论如何,即使没有 PK,也可以作为唯一标识行的一种方式(或者您可以通过使用 SSMS 打开表格来编辑该行)。但是使用主键和 Sql 命令似乎更有效。
      • @Lluis,您使用 DELETE...LIMIT 1 或 UPDATE...LIMIT 1。@Cyber​​herbalist,行不能总是唯一标识,因为没有什么可以阻止所有列值相同,但是您可以限制受查询影响的数量。
      【解决方案8】:

      有钥匙和关系很好。有很大帮助。但是,如果您的应用程序足以处理关系,那么您可能会跳过键(尽管我建议您拥有它们)

      【讨论】:

        【解决方案9】:

        由于我使用 Subsonic,我总是为我的所有表创建一个主键。许多数据库抽象库需要一个主键才能工作。

        注意:这并不能回答您问题的“大统一理论”基调,但我只是说在实践中,有时您必须为每个表创建一个主键。

        【讨论】:

          【解决方案10】:

          如果它是一个连接表,那么我不会说你需要一个主键。例如,假设您有表 PERSONS、SICKPEOPLE 和 ILLNESSES。 ILLNESSES 表有流感、感冒等,每个都有一个主键。 PERSONS 有关于人的常用资料,每个资料也有一个主键。 SICKPEOPLE 表中只有生病的人,它有两列,PERSONID 和 ILLNESSID,外键返回到各自的表,没有主键。 PERSONS 和 ILLNESSES 表包含实体,实体获取主键。 SICKPEOPLE 表中的条目不是实体,也没有主键。

          【讨论】:

          • 我可能会在 SICKPEOPLE 表(包括两列)上放置一个主键(或至少一个唯一索引),以确保您不会意外插入同一行两次。跨度>
          • 好点。正如您所说,您可以通过在 SICKPEOPLE 表中的 PERSONID 和 ILLNESSID 的组合上添加唯一约束或索引来避免重复插入的问题。目前我倾向于不向这样的表添加主键,因为它有助于明确它不是实体。
          【解决方案11】:

          数据库本身没有键,但它们的组成表可能。我猜你的意思是,但以防万一......

          不管怎样,行数多的表绝对应该有主键;只有几行的表不一定需要它们,尽管它们不会造成伤害。这取决于表的用途和大小。纯粹主义者会将主键放在每个表中。这没有错;也不是在小表中省略 PK。

          已编辑以添加一个指向我关于此问题的博客条目的链接,其中我讨论了数据库管理人员认为没有必要在特定表中包含主键的情况。我认为这充分说明了我的观点。

          Cyberherbalist's Blog Post on Primary Keys

          【讨论】:

          • 单行表不需要主键,其他任何东西都应该定义一个以避免重复。
          • 是的,一般来说,但业务规则决定是否允许重复 - 表中的重复条目可能不仅是允许的,而且是预期的,这并非不可想象。这取决于存储的是什么,以及它的用途。顺便说一句,感谢代表命中 - 这个答案实际上与接受的答案并不矛盾。注意到你的专制。
          • 如果您存储完全重复的内容,那么您存储的内容是错误的。至于rep hit,去掉那些认为每张桌子都应该有PK的人的猛烈抨击,我会去掉它。
          • 没有“大满贯”的意思。你个人有被我写的东西冒犯吗?如果是这样,我很抱歉,但为了纯粹起见,我不会修改我的答案,只是在我的博客文章中添加一个关于这个问题的链接。保持你的反对票。我不会屈服于恐吓。
          • 赞成。并且不会因为被称为“纯粹主义者”而被冒犯......但是无键表恰好在使用时具有唯一值,充其量是令人困惑的,最坏的情况是危险的(尤其是当代码将这些表视为确实 i> 有钥匙)。拥有一把钥匙不会造成伤害,拥有一把钥匙可以,或者应该说,——总有一天,墨菲定律规定。
          猜你喜欢
          • 2011-05-30
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-01-31
          • 2013-05-06
          • 1970-01-01
          • 2010-09-18
          相关资源
          最近更新 更多