额外的表或非特定的外键?
-
09-06-2019 - |
题
系统中有多种类型的对象,每种对象在数据库中都有自己的表。用户应该能够对其中任何一个进行评论。您将如何设计评论表?我可以想到几个选择:
- 一个注释表,每个对象类型(ObjectAID、ObjectBID 等)都有一个 FK 列
- 多个注释表,每个对象类型对应一个(ObjectAComments、ObjectBComments 等)
- 一个通用 FK (ParentObjectID),另一列指示类型(“ObjectA”)
你会选择哪个?还有我没有想到的更好的方法吗?
解决方案
@palmsey
差不多,但是我最常看到的那种模式的变化摆脱了 ObjectAID
等人。 ParentID
既成为PK又成为FK Parents
. 。这会让你得到类似的东西:
Parents
ParentID
ObjectA
ParentID
(FK 和 PK)ColumnFromA NOT NULL
ObjectB
ParentID
(FK 和 PK)ColumnFromB NOT NULL
Comments
将保持不变。然后你只需要限制 ID 的生成,这样你就不会意外地得到一个 ObjectA
行和一个 ObjectB
两者都指向相同的行 Parents
排;最简单的方法是使用您正在使用的相同序列(或其他序列) Parents
为了 ObjectA
和 ObjectB
.
您还会看到很多类似以下内容的模式:
Parents
ID
SubclassDiscriminator
ColumnFromA (nullable)
ColumnFromB (nullable)
和 Comments
将保持不变。但现在,如果不编写触发器或在不同的层执行此操作,则无法强制执行所有业务约束(子类的属性均可为空)。
其他提示
设计架构以使可注释(由于缺乏更好的词)表遵循标准继承建模模式之一是否可行?如果是这样,您可以让注释表的 FK 指向公共父表。
@汉克·盖伊
所以像这样:
- 对象A
- 对象辅助工具
- 家长ID
- 对象B
- 对象BID
- 家长ID
- 评论
- 评论ID
- 家长ID
- 父母
- 家长ID
请小心不完全指向一张表的通用外键。如果必须拆分类型上的 where 条件并指向多个不同的表,查询性能会受到极大影响。如果您只有几种类型,并且类型的数量不会增长,那么可以为不同的表设置单独的可为空外键,但如果您有更多类型,最好提出不同的数据模型(例如@palmsey 的建议)。
我喜欢做的一件事是拥有一个单独的表,将通用/公用表链接到所有个性化表。
因此,对于对象 Foo 和 Bar,然后对 Foo 和 Bar 进行注释,您将得到如下所示的内容:
- 富
- Foo ID(PK)
- 酒吧
- 酒吧 ID (PK)
- 评论
- 评论 ID (PK)
- 评论文字
- Foo评论
- Foo ID (PK FK)
- 评论 ID (PK FK)
- 评论栏
- 酒吧 ID (PK FK)
- 评论 ID (PK FK)
这个结构:
- 让您拥有一个共同的评论表
- 不需要具有表继承的数据库
- 不会用 Comment 相关信息污染 Foo 和 Bar 表
- 让您可以附加评论 多种的 对象(可以是期望的)
- 如果需要,允许您将其他属性附加到 Foo/Bar 和 Comment 的交界处。
- 仍然保留与标准的关系(即:快速、简单、可靠)外键