postgresql 在SQL中对M:N关系建模的正确方法,其中父关系可能是多种类型之一

niknxzdl  于 2022-11-04  发布在  PostgreSQL
关注(0)|答案(2)|浏览(145)

我遇到了一种情况,一个特定的子对象可能有多个不同类型的父对象。例如,一个foo对象可能是一个或多个abc对象的子对象。此外,我还有一个bar对象,它也可能是一个或多个ab或者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似乎是最容易查询和回答Find all the parents of child 7Find all the children of parent 4之类的问题的,但我读过一些建议,基本上是说永远不要为父/子关系创建通用表。
有没有人能告诉我们最好的方法和为什么?可以肯定的是,表中的行永远不会超过几百万行。

6pp0gazn

6pp0gazn1#

我建议您使用解决方案C的变体。您需要为每个M:N关系使用一个单独的M:N表(按照Fourth Normal Form)。
而且还要创建一个超表来统一所有的a、b、c父类型,以便M:N表可以引用单个表,其中每个parent_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_table对(parent_id,parent_type)具有唯一约束条件,并且每个子父代表中的外键引用该唯一约束条件中的列。因此,没有parent_id可以被多个子类型引用。
然后,子M:N表只需要按ID引用parent_table。这些表中不一定需要parent_type列,但如果需要在(child_id,parent_type)上创建UNIQUE约束,以便每个子表只能有一个给定类型的父表,则需要这样做。

foo_parent_tbl
child_id parent_id
-------- ---------
5         1
6         2

bar_parent_tbl
child_id parent_id
-------- ---------
7        3
7        4

您可能还想阅读:

2ledvvac

2ledvvac2#

只要类型a、B、c、d始终是父项,而类型foo和bar只能是子项(即'foo'可能/永远不会是'c'的父项),则每个实体都应有一个表,关系也应有一个表。一个表用于父项(parent_id,parent_type),一个表用于子项(child_id,child_type),一个表用于关系(parent_id,child_id)。

相关问题