我对关系数据库中的superype-subtype desing有疑问。如果我有一个带有两个子类型表的超类型,我会将超类型的PK与两个子类型表的PK相关联作为FK。假设我有这样的事情:
TypeID PK
ID PK TypeID FK
ID PK,FK
ID PK,FK
在数据库方面,我如何确保给定类型的超类型ID仅被放入适当的子类型表中?例如,我不希望将带有类型A的超类型ID放入SubtypeB表中。有没有办法轻松防止这种情况发生在数据库端?我知道这可以在代码中处理,但如果代码有错误怎么办?或者,如果有人手动将错误的ID输入其中一个子类型表,该怎么办?我想我正在寻找一些方法让这在数据库方面变得不可能。
有什么想法吗?也许Supertype表上的PK应该是ID和TypeID组合,ID列上有唯一约束,以防止两种类型的记录都在SuperType表中...然后子类型表将具有组合ID和TypeID PK对TypeID的约束只能是适当的子类型表的类型??
答案 0 :(得分:6)
在数据库方面,我如何确保给定类型的超类型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)
)
)
这些特殊的圆形FKs 1 与CHECK相结合,确保了孩子的排他性和存在(CHECK确保其中一个:{ {1}},SuprerType.SubtypeAId
为非NULL且与SuprerType.SubtypeBId
匹配。推迟孩子FK(或者如果你的DBMS支持它,检查CHECK)以在插入新数据时打破鸡与蛋的问题。
1 SuperTypeId
引用SubtypeA.SubtypeAId
和SuperType.SuperTypeId
引用SuperType.SubtypeAId
,同样适用于其他子类型。
如果您的DBMS不支持延迟约束,您可以允许(在CHECK中)两个字段都为NULL并放弃执行子项的存在(您仍然保持排他性)。
或者,也可以强制执行排他性(但不是存在):
注意:如果DBMS不支持“非关键”FK,则可能需要在SubtypeA.SubtypeAId
上添加冗余UNIQUE。
SuperType {SuperTypeId, TypeId}
上有以下约束:
SubtypeA
CHECK(TypeId = 1)
上的以下约束:
SubtypeB
我用1和2表示特定的亚型 - 你可以使用任何你喜欢的东西,只要你是一致的。
此外,您可以考虑使用子类型CHECK(TypeId = 2)
的计算列(例如Oracle 11 virtual columns)来节省存储空间。
最后,“单独表中的所有类”并不是实现继承的唯一策略。如果使用“一个表中的所有内容”或“单独表中的具体类”实现继承,则强制执行子类型的存在和排他性变得更加容易。
请查看this post了解详情。
答案 1 :(得分:0)
使用触发器将超类型表中的新条目传播到相应的子类型表。