【问题标题】:Three level database - foreign keys三级数据库 - 外键
【发布时间】:2010-05-02 20:12:38
【问题描述】:

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

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 的外键是否必要?或者考虑到所有这些列都是主键的一部分,我什至根本不需要外键?

谢谢。

【问题讨论】:

    标签: database-design foreign-keys


    【解决方案1】:

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

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

    表 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 将有一个由四列组成的复合主键。在某些时候,这开始让人觉得很傻。我曾经在一个系统上工作过,该系统有一个带有 9 个 主键列和两个数据列的表 J。

    另外,复合键也可以与业务键相关联。将它们作为外键传播可能会让人头疼。一旦我们决定为一个表使用代理(合成)键——自动增量、序列、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 中的一个子集来限制对我们所有表的访问。

    所以这不是一个硬性规定。在争论的双方,人们对此都有强烈的感受。在我的职业生涯中,我强烈支持复合主键,但现在我发现自己通常倾向于单列主键,并在适当的时候使用唯一约束来强制执行复合业务键。

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

    【讨论】:

    • 使用复合主键有什么不好?对于 B/C 中的每个新块,对于从 1 开始的整数索引,我比连续标识符更有用。
    • 非常感谢您的编辑。我只会有这三个级别,并且分开的关键数字肯定会对这个项目有所帮助,但我会在下一个项目中记住你的论点。再次感谢!
    【解决方案2】:

    如果您在表 B 和表 A 之间已经有一个外键,以确保表 B 只包含表 A 中存在的具有 a_id 值的条目,那么表 C 和表 A 之间的额外 FK 在 @ 987654322@ 是不必要的。当然,这要求表 B 和表 A 之间的 FK 关系是强制的、活动的,并且不能以任何方式禁用或规避。

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

    【讨论】:

    • 啊,所以我不需要外键来表达不同表的实际关系,而只是为了保持完整性?
    猜你喜欢
    • 1970-01-01
    • 2016-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-10-06
    • 2021-09-05
    • 2018-11-08
    • 2014-10-22
    相关资源
    最近更新 更多