【问题标题】:SQL Primary Key - is it necessary?SQL 主键 - 有必要吗?
【发布时间】:2012-01-08 12:33:59
【问题描述】:

我有一个物品清单。这些物品中的大部分都没有库存。 item 表有 id、name、description。项目的数量存储在另一个名为 inventory 的表中。库存表具有 item_id 和库存商品的数量。

库存表需要主键吗?如果是这样,我应该使用串行密钥还是复合密钥?表什么时候可以没有主键?

编辑:感谢大家提供的非常丰富的信息。除了极少数例外,我现在将始终拥有主键。我还学到了更多关于串行键和复合键的知识。

【问题讨论】:

  • ANY 真实数据表需要一个主键 - 这是唯一标识表中每一行的方法。为什么你会想要一个 PK 超出我的范围......我在表上没有主键的唯一情况可能是用于批量加载数据或其他东西的临时表就这样……
  • @mark_s 与这个问题没有任何联系,但我个人认为,在非常特殊的情况下,我可以比基于 PK 的表更好地拥有和利用堆 8-) 让我们去聊天?
  • @mark_s 是的,确切地说,只有批量加载的堆规则 8-)
  • @OlegDok:暂存表是没有集群 PK 的堆/表的唯一现实案例
  • @gbn 就是这个意思,过段时间@dba.se会有一个关于PK的问题

标签: sql key primary-key composite-key composite-primary-key


【解决方案1】:

库存表需要主键吗?

我们可以假设数据是相关的吗?根据定义,关系没有重复的元组。 SQL 允许表中有重复的行。因此,为了确保在实践中没有重复行,每个表都应该至少有一个唯一约束。长话短说,您最好有充分的理由不对表中的每个候选键设置唯一约束。根据定义,可以将零个或一个候选键指定为“主键”,而哪一个(如果有)应该接受此指定是任意的。

我应该使用串行密钥还是复合密钥?

我认为这是一个错字。单列键称为“简单键”而不是“序列键”。根据您的描述,您的 Inventory 表在 item_ID which is a simple key 上有一个唯一的候选候选键。唯一可能的复合键是超键,除非它被外键引用,否则不应使用唯一约束进行约束。

什么时候表可以没有主键?

当所有候选键都已使用UNIQUE 约束或表不打算保存关系数据时。

【讨论】:

    【解决方案2】:

    始终以拥有一个主键为目标。

    如果你不确定,有一个主键。

    即使您有 99.99% 的把握不会需要它,也请拥有一个。根据我多年的经验,需求会发生变化。

    我真正能想到的唯一示例是只有两个foreign_keys 的多对多表和每个字节都很重要的巨型(数亿行)表。但即便如此,仍然强烈建议使用单独的、唯一的、无业务价值的 id 键。

    这里有更多关于此的重要信息:
    http://weblogs.sqlteam.com/jeffs/archive/2007/08/23/composite_primary_keys.aspx

    这里:
    http://www.techrepublic.com/article/the-great-primary-key-debate/1045050
    在这里:
    http://databases.aspfaq.com/database/what-should-i-choose-for-my-primary-key.html
    在这里:
    Should I use composite primary keys or not?

    在你的例子中,我肯定会有一个。

    “不”拥有一个的决定应该基于非常明确的需求和理解以及拥有一个的实际或预测(例如数量)问题。

    调试和故障排除时出现了这种需求的一个很好的例子。就像在每个表中创建和更新列(我最喜欢的另一个)一样,此信息最初可能不会被前端使用/用于前端,但男孩可以帮助跟踪和解决问题。 (顺便说一句,更新戳现在通常是像 Ruby On Rails 这样的框架的标准配置,它也适用于每个具有 id 字段的表的约定!)

    【讨论】:

    • The only examples I can really think of are many-to-many tables with just two foreign_keys - 为什么不把两个外键也变成复合主键呢?
    【解决方案3】:

    一般来说:每个表都应该有一个 PK。至少每个表都应该有一些 CLUSTER 索引。 PK 不能是一个特殊的列,但是在系统 (RDBMS) 中没有唯一标识的行是不好的做法。

    可能有几种情况不需要 PK,但这是规则中的例外情况。

    【讨论】:

    • 聚集索引是索引的物理实现细节,与是否需要 PK 的问题完全无关。此外:并非每个 DBMS 都有聚集索引
    • a_horse_with_no_name:如果 DBMS 没有用户定义的集群索引,那么 DBMS 有自己的内部方式,如何对数据进行集群。当然 - 如果您的 DBMS 是这种情况,请忽略我关于该 DBMS 的 CLUSTER 的注释:)。
    【解决方案4】:

    如果 item_id 在库存表中是唯一的,我会说你可以使用它作为标识符。主键通常用于唯一标识行,但我可以看到,在您的情况下,库存行标识没有用处。

    编辑:正如其他人所指出的,通常如果您没有充分的理由使用主键,那么您最好查看表结构以查看是否可以将其与另一个表合并,在这种情况下可能是项目表。我可以看到这不是一个选项的情况(例如,您不能更改架构,只需添加新表)但值得一看。

    【讨论】:

      【解决方案5】:

      如果每件商品只有一个库存行 - 那么它会在同一个商品表中便宜得多(平均 CPU 和 IO),

      如果不是 - 这取决于。而且它根本不是标准化数据

      但据我了解,如果您坚持在两个表上 - 是的,最好在 item_id 字段上建立索引

      【讨论】:

      • 我还在考虑是否应该将这两个表合并在一起,感觉有些不对劲。感觉每个表中描述的实体相似但不完全相同。
      • 两张表只有在您有类似交付的每件商品的单独价格时才有意义,否则您可以轻松地将它们合并在一起
      • 嗯,好吧,你的积分被占用了。我会将它们合并在一起。我已经得出结论,数量属于项目实体。我的理由是项目表在每一行中描述了一个项目,并且数量仍在描述该项目。也许我会将表格重命名为 Items,因为每一行描述的项目不止一个项目......或者不是因为 1 个项目非常愚蠢。
      • 虽然你提出了有趣的观点,但迈克尔回答了所有三个问题。
      • 我猜英语不是你的第一语言,但我怀疑这里有更深层次的问题。标准化为最高可能的范式,即 6NF,似乎需要至少三个表,可能更多。我根本看不出使用两个表会如何违反 1NF。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-10-03
      • 2012-12-14
      • 2018-02-28
      • 2010-10-19
      • 1970-01-01
      相关资源
      最近更新 更多