简体   繁体   English

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

[英]Proper way to model M:N relationship in SQL where parent may be one of many types

I have a situation where a particular child object may have multiple parents of different types. 我遇到一个特定的子对象可能具有多个不同类型的父对象的情况。 For example, a foo object may be a child of one ore more of a , b , or c objects. 例如, foo对象可以是abc对象中a或多个的子对象。 More over, I also have a bar object which may also be a child of one or more a , b , or c objects. 而且,我还有一个bar对象,它也可以是abc对象的一个​​或多个。 What's the proper way to model this in SQL? 在SQL中对此建模的正确方法是什么?

A) Single table for all relationships: 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) Unique table for each parent type: 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) Unique table for each child type: 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) Unique table for each combination 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) Some other strategy that I haven't explored E)我没有探索过的其他策略

To me, it seems like A would be the easiest to query and answer questions like Find all the parents of child 7 or Find all the children of parent 4 , but I've read some advice that basically says never create generic tables for parent/child relationships. 对我来说,似乎A是最简单的查询和回答问题,例如“ Find all the parents of child 7或“ Find all the children of parent 4 ,但我读过一些建议,基本上说从不为父母/创建通用表儿童关系。

Could somebody shed some light on the best way to do this and why? 有人可以阐明这样做的最佳方法吗?为什么? It's safe to assume that the table will never have more than a few million rows in it. 可以肯定地说,表中的行永远不会超过几百万行。

I'd recommend a variation of your solution C. You need to have a separate M:N table for each M:N relationship, per Fourth Normal Form . 我建议您使用解决方案C的一种变体。对于每个M:N关系,您都需要有一个单独的M:N表(根据“ 第四范式”)

But also create a supertable to unify all the a, b, c parent types, so that the M:N tables can reference a single table, in which each parent_id is strictly assigned its respective type. 而且还要创建一个上表,以统一所有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

In each sub-parent table, the parent_type is restricted to a single value. 在每个子父表中, parent_type被限制为单个值。 The parent_table has a unique constraint on (parent_id, parent_type), and the foreign key in each sub-parent tables references the columns in that unique constraint. parent_table对(parent_id,parent_type)具有唯一约束,并且每个子父表中的外键引用该唯一约束中的列。 Therefore no parent_id can be referenced by more than one sub-type. 因此,任何一个以上的子类型都不能引用parent_id。

Then your child M:N tables only need to reference parent_table by ID. 然后,您的子M:N表仅需parent_table ID引用parent_table You don't necessarily need a parent_type column in these tables, but you do if you need to create a UNIQUE constraint over (child_id, parent_type) so that each child can have only one parent of a given type. 这些表中不一定需要有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

You may also like to read: 您可能还喜欢阅读:

As long as types a,b,c,d are always parents, and types foo and bar can only be children (ie 'foo' could/will never be a parent of 'c') You should have a table for each entity and a table for the relationships. 只要类型a,b,c,d始终是父项,而类型foo和bar只能是子项(即“ foo”可能/将永远不是“ c”的父项),则您应该为每个实体都有一个表,并且关系表。 One table for parents (parent_id, parent_type), One table for children (child_id, child_type), and One table for relationships (parent_id, child_id). 一张表用于父母(parent_id,parent_type),一张表用于孩子(child_id,child_type)和一张关系表(parent_id,child_id)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM