超类型-子类型数据库设计

5
我有一个关于关系型数据库中超类型-子类型设计的问题。如果我有一个带有两个子类型表的超类型,我将把超类型的PK与两个子类型表的PK相关联作为FK。比如说我有这样一些东西:

Type

TypeID PK

SuperType

ID PK TypeID FK

SubtypeA

ID PK,FK

SubtypeB

ID PK,FK

在数据库方面,如何确保给定类型的超类型ID仅被放入相应的子类型表中?例如,我不想让类型A的超类型ID被放入SubtypeB表中。有没有一种简单的方法来防止这种情况在数据库端发生?我知道这可以在代码中处理,但如果代码出错怎么办?或者如果有人手动输入了错误的ID到其中一个子类型表中怎么办?我想找到一种在数据库端使这种情况不可能发生的方法。
有什么想法吗?也许超类型表上的PK应该是ID和TypeID组合,并在ID列上设置唯一约束条件以防止在SuperType表中出现两种类型的记录...然后子类型表将具有组合ID和TypeID PK,并对TypeID设置约束条件,只能是适当子类型表所需的类型?

可能是数据库设计问题的重复。 - Mike Sherrill 'Cat Recall'
如何在子类型中实现引用完整性中回答了。 - undefined
2个回答

12
在数据库方面,我该如何确保给定类型的超类型ID仅放入相应的子类型表中?
在支持延迟约束的DBMS上,您可以执行以下操作:

enter image description here

以下是对 SuperType 的约束条件:

CHECK (
    (
        (SubtypeAId IS NOT NULL AND SubtypeAId = SuperTypeId)
        AND SubtypeBId IS NULL
    )
    OR
    (
        SubtypeAId IS NULL
        AND (SubtypeBId IS NOT NULL AND SubtypeBId = SuperTypeId)
    )
)

这些奇特的循环FKs与CHECK相结合,确保子项的排他性和存在性(CHECK确保以下情况之一:SuprerType.SubtypeAId,SuprerType.SubtypeBId非空且匹配SuperTypeId)。在插入新数据时,延迟子项FKs(或CHECK,如果您的DBMS支持)以打破鸡生蛋问题。
1 SubtypeA.SubtypeAId引用SuperType.SuperTypeId,SuperType.SubtypeAId引用SubtypeA.SubtypeAId,其他子类型同理。
如果您的DBMS不支持延迟约束,则可以允许(在CHECK中)两个字段都为空,并放弃对子项存在性的强制执行(仍保留排他性)。

或者,只有独占性(但不是存在性)也可以这样实施:

enter image description here

注意:如果数据库管理系统不支持“非关键字”外键,则可能需要在 SuperType {SuperTypeId,TypeId} 上添加一个冗余的UNIQUE。

对于 SubtypeA 的以下约束:

CHECK(TypeId = 1)

下面是对 SubtypeB 的约束条件:

CHECK(TypeId = 2)

我使用1和2来表示具体的子类型 - 你可以使用任何你喜欢的,只要你保持一致即可。

此外,你可以考虑为子类型的TypeId(例如Oracle 11 virtual columns)使用计算列来节省存储空间。


顺便提一下,通过应用程序逻辑来强制存在和排他性并不被认为是一个不好的整体策略。大多数情况下,你应该努力将尽可能多的完整性强制放在数据库中,但在这种特定情况下,通过应用程序级别进行操作通常被认为是合理的,以避免上述复杂性。


最后,“所有类别在单独的表格中”并不是实现继承的唯一策略。如果您使用“一个表格中的所有内容”或“具体类别在单独的表格中”来实现继承,则可以更轻松地强制执行子类型的存在和排他性。
请查看此帖子以获取更多信息。

0
使用触发器将超类型表中的新条目传播到适当的子类型表中。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接