三级数据库 - 外键

时间:2010-05-02 20:12:39

标签: database-design foreign-keys

我有一个具有以下结构的三级数据库(简化为仅显示主键):

Table A: a_id
Table B: a_id, b_id
Table C: a_id, b_id, c_id

因此表C的可能值是这样的:

a_id  b_id  c_id
   1     1     1
   1     1     2
   1     1     3
   1     2     1
   1     2     2
   2     1     1
   2     2     1
   2     2     2
...

我现在不确定,应该如何设置外键;或者是否应该为主键设置它们。我的想法是在表B B.a_id -> A.a_id上有一个外键,在C C.a_id -> A.a_id( C.a_id, C.b_id ) -> ( B.a_id, B.b_id )上有两个外键。

这是我设置外键的方式吗?来自C->A的外键是否必要?或者我甚至需要外键,因为所有这些列都是主键的一部分?

感谢。

2 个答案:

答案 0 :(得分:3)

首先,必须使用外键来断言父表中是否存在记录,而主键则使用表来声明记录的唯一性。所以你需要两者。

一般来说,您希望避免使用复合主键。所以你的表应该是这样的:

表A:a_id(pk)
表B:b_id(pk),a_id(fk)
表C:c_id(pk),b_id(fk)

表C和表A之间不需要外键,因为表C和表B以及表B和表A之间的外键暗示了这种关系。

修改

  

使用化合物有什么不好   主键?

将表C连接到表B时,只需要少一行。当我们传播外键时,列数会累积,因此表D将具有四列的复合主键。在某些时候,这开始感到愚蠢。我曾经在一个系统上工作,该系统的表J带有 9个主键列和两个数据列。

另一方面,复合键也可以与业务键相关联。将那些作为外键传播可能是一个真正的痛苦。一旦我们决定为一个表使用代理(合成)密钥 - 自动增量,序列,guid,等等 - 一致性表明我们应该对所有表使用相同的主键机制。

有一些ORM工具使得复合键难以使用。我不认为这是不使用复合键的一个很好的理由,因为我强烈反对驱动我的数据模型的ORM工具的局限性,我只是指出它。

另一方面,使用复合键可能是有利的。我在一个系统上工作,我们不得不对格式进行大量查询

select D.* 
from  D 
    join A on ( D.a_id = A.id )
where A.some_col = 'whatever'

不必将表D连接到表C到表B以获得表A是一个明确的福音。当用户可以访问表A中托管子集的基础上,他必须限制对所有表的访问时,这甚至可以更真实地实现虚拟专用数据库。

所以这不是一个硬性规定。在争论的两个方面,人们都对这一点感到强烈。在我的职业生涯中,我强烈支持复合主键,但现在我发现自己通常会支持单列主键,并在适当的时候使用复合业务键强制执行。

简而言之,复合主键不是错误只是笨重。单列,代理主键可能是行业标准。但是,有些情况下复合主键是正确的选择。

答案 1 :(得分:1)

如果表B和表A之间已经有一个外键,以确保表B只包含表A中存在a_id值的条目,那么表C和表A之间的额外FK a_id上没有必要。当然,这要求表B和表A之间的FK关系被加密,激活,而不是以任何方式禁用或规避。

在表C和表B之间建立FK链接已经保证TableC.a_id只能引用有效值a_id(因为表B中通过表B和表之间的FK关系保证了这一点) A)。