超类型子类型数据库设计

C C*_*C C 4 database database-design

我有一个关于关系数据库中超级子类型设计的问题.如果我有一个带有两个子类型表的超类型,我会将超类型的PK与两个子类型表的PK相关联作为FK.假设我有这样的事情:

类型

TypeID PK

ID PK TypeID FK

SubtypeA

ID PK,FK

SubtypeB

ID PK,FK

在数据库方面,我如何确保给定类型的超类型ID只被放入适当的子类型表中?例如,我不希望将带有类型A的超类型ID放入SubtypeB表中.有没有办法轻松防止这种情况发生在数据库端?我知道这可以在代码中处理,但如果代码有错误怎么办?或者,如果有人手动将错误的ID输入其中一个子类型表,该怎么办?我想我正在寻找一些让数据库方面无法实现这一目标的方法.

有任何想法吗?也许Supertype表上的PK应该是ID和TypeID组合,ID列上有唯一约束,以防止两种类型的记录都在SuperType表中...然后子类型表将具有组合ID和TypeID PK对TypeID的约束只能是适当的子类型表的类型?

Bra*_*vic 10

在数据库方面,我如何确保给定类型的超类型ID只被放入适当的子类型表中?

在支持延迟约束的DBMS上,您可以执行以下操作:

在此输入图像描述

具有以下约束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)
    )
)
Run Code Online (Sandbox Code Playgroud)

这些特殊的圆形FK 1与CHECK相结合,确保了孩子的排他性存在性(CHECK确保了以下之一:SuprerType.SubtypeAId,SuprerType.SubtypeBId非NULL并匹配SuperTypeId).推迟子FK(或者如果你的DBMS支持它,则检查CHECK)以在插入新数据时打破鸡与蛋的问题.

1 SubtypeA.SubtypeAId参考SuperType.SuperTypeIdSuperType.SubtypeAId参考SubtypeA.SubtypeAId,同样的另一个子类型.

如果您的DBMS不支持延迟约束,您可以允许(在CHECK中)两个字段都为NULL并放弃执行子项的存在(您仍然保持排他性).


或者,也可以强制执行排他性(但不是存在),如下所示:

在此输入图像描述

注意:SuperType {SuperTypeId, TypeId}如果DBMS不支持"非关键"FK ,则可能需要添加冗余UNIQUE .

具有以下约束SubtypeA:

CHECK(TypeId = 1)
Run Code Online (Sandbox Code Playgroud)

以下约束SubtypeB:

CHECK(TypeId = 2)
Run Code Online (Sandbox Code Playgroud)

我用1和2来表示特定的亚型 - 你可以使用任何你喜欢的东西,只要你是一致的.

此外,您可以考虑使用子类型的计算列TypeId(例如Oracle 11 虚拟列)来节省存储空间.


顺便说一句,通过应用程序逻辑强制执行存在和排他性并不是一个糟糕的整体策略.大多数情况下,您应该尽可能多地在数据库中执行完整性强制执行,但在这种特殊情况下,在应用程序级别执行它通常被认为是合理的,以避免上述复杂性.


最后,"单独表中的所有类"并不是实现继承的唯一策略.如果使用"一个表中的所有内容"或" 单独表中的具体类"实现继承,则强制执行子类型的存在和排他性变得更加容易.

看一下这篇文章了解更多信息.


Wal*_*tty 0

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