在SQL中为M:N关系建模的正确方法,父关系可能是多种类型之一
我有一种情况,一个特定的子对象可能有多个不同类型的父对象。例如,在SQL中为M:N关系建模的正确方法,父关系可能是多种类型之一,sql,postgresql,foreign-keys,relational-database,polymorphic-associations,Sql,Postgresql,Foreign Keys,Relational Database,Polymorphic Associations,我有一种情况,一个特定的子对象可能有多个不同类型的父对象。例如,foo对象可以是a、b或c对象中一个或多个对象的子对象。此外,我还有一个bar对象,它也可能是一个或多个a、b或c对象的子对象。在SQL中对此进行建模的正确方法是什么 A) 所有关系的单个表: relationship_tbl parent_id parent_type child_id child_type --------- ----------- -------- ---------- 1 a
foo
对象可以是a
、b
或c
对象中一个或多个对象的子对象。此外,我还有一个bar
对象,它也可能是一个或多个a
、b
或c
对象的子对象。在SQL中对此进行建模的正确方法是什么
A) 所有关系的单个表:
relationship_tbl
parent_id parent_type child_id child_type
--------- ----------- -------- ----------
1 a 5 foo
2 a 6 foo
3 c 7 bar
4 b 7 bar
B) 每个父类型的唯一表:
a_child_tbl
parent_id child_id child_type
--------- -------- ----------
1 5 foo
2 6 foo
b_child_tbl
parent_id child_id child_type
--------- -------- ----------
4 7 bar
c_child_tbl
parent_id child_id child_type
--------- -------- ----------
3 7 bar
C) 每个子类型的唯一表:
foo_parent_tbl
child_id parent_id parent_type
--------- ----------- -----------
5 1 a
6 2 a
bar_parent_tbl
child_id parent_id parent_type
--------- ----------- -----------
7 3 c
7 4 b
D) 每个组合的唯一表格
a_foo_tbl
parent_id child_id
--------- --------
1 5
2 6
b_bar_tbl
parent_id child_id
--------- --------
4 7
c_bar_tbl
parent_id child_id
--------- --------
3 7
E) 我还没有探讨过其他一些策略
对我来说,A似乎是最容易查询和回答的问题,如查找子7的所有父项
或查找父4的所有子项
,但我读过一些建议,基本上是说永远不要为父/子关系创建通用表
有人能解释一下最好的方法吗?为什么?可以安全地假设表中的行永远不会超过几百万行。只要类型a、b、c、d始终是父级,类型foo和bar只能是子级(即“foo”可能/永远不会是“c”的父级),那么每个实体都应该有一个表,关系应该有一个表。一个表用于父对象(父对象id,父对象类型),一个表用于子对象(子对象id,子对象类型),一个表用于关系(父对象id,子对象id)。只要类型a、b、c、d始终是父对象,类型foo和bar只能是子对象(即“foo”可能/永远不会是“c”的父对象)您应该为每个实体设置一个表,并为关系设置一个表。一个表用于父项(父项id,父项类型),一个表用于子项(子项id,子项类型),一个表用于关系(父项id,子项id)。我建议您的解决方案C的一个变体。 对于每个M:N关系,您需要有一个单独的M:N表 但是还要创建一个超表来统一所有的a、b、c父类型,这样M:N表就可以引用一个表,其中每个父表的id都被严格地分配了各自的类型
parent_tbl
parent_id parent_type
--------- -----------
1 a
2 a
3 c
4 b
a_parent_tbl
parent_id parent_type
--------- -----------
1 a
1 a
b_parent_tbl
parent_id parent_type
--------- -----------
4 b
c_parent_tbl
parent_id parent_type
--------- -----------
3 c
在每个子父表中,parent_type
仅限于一个值。parent_表
对(parent_id,parent_type)有唯一的约束,每个子父表中的外键引用该唯一约束中的列。因此,多个子类型不能引用任何父类id
然后,您的子M:N表只需要按ID引用父表。这些表中不一定需要父表类型列,但如果您需要在(子表ID,父表类型)上创建唯一约束,以便每个子表只能有一个给定类型的父表,则可以这样做
foo_parent_tbl
child_id parent_id
-------- ---------
5 1
6 2
bar_parent_tbl
child_id parent_id
-------- ---------
7 3
7 4
您还可以阅读:
- 我过去对你的回答
- 我的演讲
- 我的书
parent_tbl
parent_id parent_type
--------- -----------
1 a
2 a
3 c
4 b
a_parent_tbl
parent_id parent_type
--------- -----------
1 a
1 a
b_parent_tbl
parent_id parent_type
--------- -----------
4 b
c_parent_tbl
parent_id parent_type
--------- -----------
3 c
在每个子父表中,parent_type
仅限于一个值。parent_表
对(parent_id,parent_type)有唯一的约束,每个子父表中的外键引用该唯一约束中的列。因此,多个子类型不能引用任何父类id
然后,您的子M:N表只需要按ID引用父表。这些表中不一定需要父表类型列,但如果您需要在(子表ID,父表类型)上创建唯一约束,以便每个子表只能有一个给定类型的父表,则可以这样做
foo_parent_tbl
child_id parent_id
-------- ---------
5 1
6 2
bar_parent_tbl
child_id parent_id
-------- ---------
7 3
7 4
您还可以阅读:
- 我过去对你的回答
- 我的演讲
- 我的书