如果我有两个具有多对多关系的对象,我通常会在我的数据库模式中使用多对多表对它们进行建模以将两者关联起来。但是该多对多表(或“连接表”)是否应该有自己的主键(整数自动递增)?
例如,我可能有表 A 和 B,每个表都有一个 ID,还有一个名为 A_B 的表,其外键元组为 (A_ID, B_ID)。但是 A_B 是否应该有一个自己的主键自动递增 ID 列?
添加它的优点和缺点是什么?我个人喜欢多对多连接的自然键。但是主键会增加什么额外的好处呢?
如果我有两个具有多对多关系的对象,我通常会在我的数据库模式中使用多对多表对它们进行建模以将两者关联起来。但是该多对多表(或“连接表”)是否应该有自己的主键(整数自动递增)?
例如,我可能有表 A 和 B,每个表都有一个 ID,还有一个名为 A_B 的表,其外键元组为 (A_ID, B_ID)。但是 A_B 是否应该有一个自己的主键自动递增 ID 列?
添加它的优点和缺点是什么?我个人喜欢多对多连接的自然键。但是主键会增加什么额外的好处呢?
我同意奥德所说的一切,除了
“它也不能合理地用作外键。”
在这种情况下,这是一个选择你的毒药,映射表绝对可以是父母,这只是孩子是否使用多列FK的问题。
以汽车和颜色为例。每年汽车制造商都有一定的颜色托盘,每种型号只有有限数量的这些颜色。许多 - 许多 :: 颜色到汽车模型
所以现在设计存储新车订单的订单表。很明显,颜色和型号将在订单表上。如果您对这些表中的每一个进行 FK,数据库将允许选择不正确的模型/颜色组合。(当然,您可以使用代码强制执行此操作,但不能以声明方式执行此操作。)如果您将父表设为多:多表,您将只能获得已指定的组合。
所以你宁愿有一个多列 FK 并指向一个建立在 ModelID 和 ColorID 上的 PK,还是你想要一个单列 FK?
选择你的毒药。
编辑
但如果它不是某物的父级,则没有表需要代理键。
这样的代理键除了开销之外什么都不增加。
如果您关心此表中的重复,请使用自然键,将它们设为复合主键。
扩展:
在应用程序中,此密钥将毫无意义并且将保持未使用状态。
在数据库中,它将没有任何功能,因为您无法在查询中合理地使用它来获取任何类型的有意义的结果。
它也不能合理地用作外键。
如果跟踪多对多关系的表有它自己的主键,并且该键在数据库中的任何其他位置用作外键,那么您将创建对该关系的依赖关系。这种关系永远无法消除。
例如,在汽车颜色示例中,如果汽车的颜色曾经停止使用(从多对多关系表中删除),那么任何引用主键的表(即购买历史)都会被破坏。
我已经做到了两种方式。有时它有利于在以后添加功能。例如,如果曾经有一次表中的一行包含的内容不仅仅是 2 个 id。如果您不缺少空间,我会在其中放一个,因为它不会造成伤害。有时它可能会干扰 ORM 工具,如 hibernate 或 ADO.NET,但那是次要的。
所以总结一下...... 优点 1. 允许潜在的未来增长。
缺点 1. 空间 2. 混淆了一些 ORM 工具。
经常使用术语“连接表”,但我认为我从未见过正确定义或解释过它。我个人避免使用该术语。据我了解,“连接表”是指具有两个外键(或可能超过两个?)的任何表。
我认为在具有多个外键的表中选择键的标准应该与任何其他表中的相同。问问自己需要强制执行哪些依赖项,哪些是独特的和不可约的。根据熟悉度、稳定性和简单性的标准选择键。仅在有充分理由时才添加代理键。
它并没有真正提供任何有用的东西。请记住键的用途,即唯一地引用“某物”。像这样的关联表本身并不是“某物”,而是其他两个已经有键的“某物”的持久性结构。在持久性介质(数据库)之外,它没有意义,甚至不应该真正存在或不为人所知(例如在业务领域),因此(应该)永远没有理由通过以下方式引用它自己的身份证。