使用循环引用设计关系数据库

Posted

技术标签:

【中文标题】使用循环引用设计关系数据库【英文标题】:Design relational database with circular reference 【发布时间】:2012-09-06 00:38:07 【问题描述】:

想象一下面包店。我有一张产品表,该表与配方表具有一对多关系,而配方表又与成分具有一对多关系。问题是我有一个蛋糕,但其中一种成分是糖霜,它本身就是一种产品(你不能把糖霜分解成单独的部分,因为糖霜适用于很多东西,而且蛋糕上的糖霜量可能需要更改)。这种设置的桌子设计是什么?

【问题讨论】:

“公式”和“食谱”是一回事,对吧?同一个产品可以有多个配方吗? IE。如果你用不同的方式做蛋糕,它还应该被认为是同一个蛋糕吗?您的陈述:“与公式表具有一对多关系的产品” 似乎暗示了这一点,但我不确定您是在描述数据的基本属性,还是只是在描述当前的数据库设计(可能与数据的实际外观不同)。 【参考方案1】:

成分表中的两列怎么样,一列用于实际成分,另一列将指向其他食谱。任何给定的行只会设置一个。

使用两列也可以强制执行参照完整性。

【讨论】:

【参考方案2】:

您正在寻找的实际上是一种常见的数据库设计模式,称为材料清单

这是一个很好的blog about bill of materials。

为了更轻松地使用此类设计所涉及的非层次树结构,您可以使用一种称为访问数的物理实现技术,我在对this question 的回答中对此进行了详细描述。

【讨论】:

【参考方案3】:

您似乎只有两个对象:公式和东西。一个公式用其他东西来描述东西。一件东西可能是也可能不是产品。这是一个二元属性:第三个表。该方案将类似于:

Stuff
-----
id : integer
name : string

FormulaPairs
------------
stuff_described_id : integer
ingredient_id : integer
amount : float

Product
-------
stuff_id : integer

查询示例:

获取Apple Pie的所有成分ID:

select ingredient_id from Stuff s inner join FormulaPairs p
where s.id == p.stuff_described_id and s.name == 'Apple Pie'

获取所有产品名称:

select name from Stuff s inner join Product p where s.id == p.stuff_id

【讨论】:

以上是关于使用循环引用设计关系数据库的主要内容,如果未能解决你的问题,请参考以下文章

如何解决循环引用?

检测到实体框架自引用循环

如何规范用户、引用和标签之间的(数据库)关系?

CoreData 引用

映射核心数据关系的正确方法

如何处理 Django 模型中的循环关系?