超类型子类型数据库设计

时间:2012-09-04 01:30:33

标签: database database-design

我对关系数据库中的superype-subtype desing有疑问。如果我有一个带有两个子类型表的超类型,我会将超类型的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的约束只能是适当的子类型表的类型??

2 个答案:

答案 0 :(得分:6)

  

在数据库方面,我如何确保给定类型的超类型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 1 与CHECK相结合,确保了孩子的排他性存在(CHECK确保其中一个:{ {1}},SuprerType.SubtypeAId为非NULL且与SuprerType.SubtypeBId匹配。推迟孩子FK(或者如果你的DBMS支持它,检查CHECK)以在插入新数据时打破鸡与蛋的问题。

1 SuperTypeId引用SubtypeA.SubtypeAIdSuperType.SuperTypeId引用SuperType.SubtypeAId,同样适用于其他子类型。

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


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

enter image description here

注意:如果DBMS不支持“非关键”FK,则可能需要在SubtypeA.SubtypeAId上添加冗余UNIQUE。

SuperType {SuperTypeId, TypeId}上有以下约束:

SubtypeA

CHECK(TypeId = 1) 上的以下约束:

SubtypeB

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

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


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


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

请查看this post了解详情。

答案 1 :(得分:0)

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