包含两个外键列的数据库表是否应该有第三列作为主键?

时间:2010-06-21 15:13:58

标签: database database-design primary-key

我猜不是,因为外键是他们自己的表中的主键,所以它们将是唯一的。

更多信息

我正在使用MySQL,以下三个表正在使用InnoDB引擎。

=======================    =======================
| galleries           |    | images              |
|---------------------|    |---------------------|
| PK | gallery_id     |    | PK | image_id       |
|    | name           |    |    | title          |
|    | description    |    |    | description    |
|    | max_images     |    |    | filename       |
|    | enabled        |    |    | enabled        |
=======================    =======================

========================
| galleries_images     |
|----------------------|
| FK | gallery_id      |
| FK | image_id        |  <----- Should I add a PK to this table?
========================

<击> 后记

<击>

感谢您的出色答案。我了解了复合键,在考虑了我的具体情况后,我决定将image_id表中的galleries_images列作为主键。这样,图像可能只与一个图库相关联,这就是我想要的。

我还将在order_num中实现galleries_images列,我将使用PHP逻辑进行维护。这样,用户可以按照特定顺序在每个图库中放置图像。我最终得到了这个:

============================
| galleries_images         |
|--------------------------|
| PK, FK | image_id        |
| FK     | gallery_id      | 
|        | order_num       |
============================

再次感谢!

Epilogue II

感谢那些指出我甚至不需要这张桌子的人。我没有提供最完整的信息。我最终完全删除了galleries_images表,只是将gallery_id作为外键添加到images表中。无论如何,我仍然学到了比我想象的更多的东西,并感谢你的帮助。

6 个答案:

答案 0 :(得分:10)

理论上,如果两个外键(FK)的组合在表中是唯一的,或者如果两个FK的组合加上一些其他列是唯一的,则该表具有复合主键,并且没有严格要求引入另一个密钥作为代理主键。但是,发现人们确实添加了额外的密钥并不罕见。在某种程度上,它取决于具有复合主键的表中的数据将用于什么。如果它描述的东西本身会有与其相关的其他表中的行,那么引入一个简单的PK可能是有意义的。

有些软件似乎需要简单的PK,即使关系数据模型没有。

答案 1 :(得分:6)

所有表都应该有一个主键。

虽然没有必要创建新的代理列来充当主键。以约翰的例子为例,拥有一个复合主键,其中包含来自其他表和日期字段的2个主键字段是完全可以接受的。

从实用的角度来看虽然有时创建新的代理列比使用复合列更容易使用,但是如果PK本身在另一个表中引用或者绑定到不处理复合主要的各种控件钥匙很好。

修改

在更新您的问题之后,我只会在gallery_id,image_id上​​创建主键复合。我没有看到添加新列的任何好处。

答案 2 :(得分:5)

答案通常是“是”。您描述的表类型是关联表,它存储关联。因为这些记录本身很有趣,并且因为您可能希望以后查找它们,所以它们应该具有有意义的身份。

例如,也许你的网球联赛有players桌子和matchups桌子。 matchups可能只包含彼此对战的两名球员的外键;它是两个玩家之间的关联

但是稍后您可能想要记录特定于该关联的其他信息:比赛发生的时间,比赛的得分等等。而且,当然,只要你想在同一个两个球员之间进行多场比赛,你就需要区分每场比赛。因此,您需要以主键的形式为每个matchup提供自己的身份。


<强>更新

========================
| galleries_images     |
|----------------------|
| FK | gallery_id      |
| FK | image_id        |  <----- Should I add a PK to this table?
========================

在您的具体示例中,在此处拥有主键可能很有用。只要您需要记录关于关联的任何元数据,您就会想要拥有该主键。此外,如果可以将同一图像多次添加到同一图库中,则需要使用主键来区分这两个记录。

答案 3 :(得分:2)

如果一个特定图像只能与一个图库相关联,那么您的图库 - 图像表中的组合是唯一的,您可以将这对字段用作PK。
如果可以复制图库 - 图像组合或者
如果你的架构包含更多的表,那些goind是那些画廊图像的孩子,
那么我建议你确实包含一个额外的字段,即PK。

答案 4 :(得分:2)

这个答案与他的锁定问题有关:我知道,应该是新主题,但无论如何。请不要仅仅为此付出代价。

例如,您可以创建一个表 Order_image_lock(图库ID(主键),start_time)。

创建3个方法/ sprocs: GetLock,CheckLock,DropLock。

如果要重新排序投资组合,请调用GetLock,其中插入(gallary_id,sysdate)。

如果有效,您可以继续。如果它在PK上失败,其他人正在重新排序,引发异常。

当您准备好重新排序时,请调用CheckLock以查看您的锁是否仍然存在(您将看到原因)如果您拥有它,请更新重新排序的值,如果没有,请转到GetLock。

完成后,DropLock删除记录。

服务器进程可以扫描表超过x分钟的锁。对于断开连接或离开屏幕并前往午餐的人。

同时向该表添加user_id列,以便您可以报告谁拥有其他用户可能需要的锁定。

这比实际锁定行要好得多。有些dbms有一定数量的锁,这会强制它们执行'lock escalation',其中多个行锁被转换为页锁,直到有太多页锁并转换为表锁...你需要检查您的RDBM适用于大型锁定卷...如果您计划扩展。

答案 5 :(得分:1)

你说外键是他们自己的表中的主键。这意味着它们在这些表中是独一无二的。但是,这并不意味着它们在此表中是独一无二的。

我一般发现最好在数据库表上创建主键。迟早,你会发现你需要它,为什么不从一开始就包括新的主键呢?