Database design 三级数据库-外键

Database design 三级数据库-外键,database-design,foreign-keys,Database Design,Foreign Keys,我有一个具有以下结构的三级数据库(简化为仅显示主键): 因此表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 ... 我现在不确定外键应该如何设置;或者是否应该为主键设置它们。我的想法是在表BB.a\u id->a.a\u

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

因此表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\u id->a.a\u id
上有一个外键,在C
C.a\u id->a.a\u id
(C.a\u id,C.B\u id)->(B.a\u id,B.B\u id)
上有两个外键

我应该这样设置外键吗?是否需要
C->A
中的外键?或者,考虑到所有这些列都是主键的一部分,我甚至需要外键吗


谢谢。

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


在表C和表B之间建立FK链接已经保证
表C.a_id
只能引用
a_id
的有效值(因为表B通过表B和表a之间的FK关系保证了这一点)。当然,这要求表B和表A之间的FK关系是加密的、活动的,而不是以任何方式禁用或规避的


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

首先,外键是断言父表中记录存在的必要条件,而主键则断言表中记录的唯一性。所以你两者都需要

一般来说,您希望避免使用复合主键。因此,您的表应该如下所示:

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
...
表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,其中有九个主键列和两个数据列

另一件事是,复合键也可以与业务键相关联。将这些作为外键传播可能是一件非常麻烦的事。一旦我们决定对一个表使用代理(合成)键(autoincrement、sequence、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中的TOW子集,所以他必须限制对所有表的访问

因此,这不是一条硬性规定。在争论的双方,人们对此都有强烈的感受。在我的职业生涯中,我一直强烈支持复合主键,但现在我发现自己通常倾向于单列主键,在适当的情况下,复合业务键必须具有唯一的约束


简言之,复合主键并没有错,只是笨拙而已。单列代理主键可能是行业标准。但是,在某些情况下,复合主键是正确的选择

首先,外键用于断言父表中记录的存在,而主键用于断言表中记录的唯一性。所以你两者都需要

一般来说,您希望避免使用复合主键。因此,您的表应该如下所示:

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
...
表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,其中有九个主键列和两个数据列

另一件事是,复合键也可以与业务键相关联。将这些作为外键传播可能是一件非常麻烦的事。一旦我们决定对一个表使用代理(合成)键(autoincrement、sequence、guid等等),一致性建议我们应该对主表使用相同的机制