Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/postgresql/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在SQL中为M:N关系建模的正确方法,父关系可能是多种类型之一_Sql_Postgresql_Foreign Keys_Relational Database_Polymorphic Associations - Fatal编程技术网

在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
您还可以阅读:

  • 我过去对你的回答
  • 我的演讲
  • 我的书

我推荐您的解决方案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
您还可以阅读:

  • 我过去对你的回答
  • 我的演讲
  • 我的书

可以使用多少种类型?它是一个有限集,还是基本上是一个无界域?它肯定是一个有限集和静态的。我正在研究大约5种不同类型的孩子,他们可能有5种不同类型的父母中的一种或多种。在这种情况下:给他们所有人一个单独的FK,并添加一个约束,即只有一个FK可以是非空的。也许有点浪费,但是干净。(在连接表的情况下:您可能需要一个代理。叹气)可以有多少种类型?它是一个有限集,还是基本上是一个无界域?它肯定是一个有限集和静态的。我正在研究大约5种不同类型的孩子,他们可能有5种不同类型的父母中的一种或多种。在这种情况下:给他们所有人一个单独的FK,并添加一个约束,即只有一个FK可以是非空的。也许有点浪费,但是干净。(在连接表的情况下:您可能需要一个代理。叹气)parent_tbl不包含a_parent_tbl、b_parent_tbl和c_parent_tbl中的所有信息吗?这三种类型需要什么?如果每个子类型都有其他子类型没有的特定属性。如果这种情况永远不会发生,那么我想您不需要这些子类型表。因此,如果我想找到某个特定父级的所有子级,我需要查询N个表,每个可能的子类型一个表。对吗?在这种型号中是的。我推荐这个模型,因为它被正确地规范化了,并且最大限度地减少了数据异常的机会。parent_tbl不包含a_parent_tbl、b_parent_tbl和c_parent_tbl中的所有信息吗?这三个模型需要什么?如果每个子类型都有其他子类型没有的特定属性。如果这种情况永远不会发生,那么我想您不需要这些子类型表。因此,如果我想找到某个特定父级的所有子级,我需要查询N个表,每个可能的子类型一个表。对吗?在这种型号中是的。我推荐这个