Sql 如何对数据库建模,使给定的实体是可扩展的?

Sql 如何对数据库建模,使给定的实体是可扩展的?,sql,database-design,entity-relationship,Sql,Database Design,Entity Relationship,我正在为我想要开发的应用程序设计一个数据库结构,我一直想知道如何设计一个实体(我使用的是Chen的符号),以便最终用户可以通过程序界面扩展它 例如,我计划编写的软件是一个食谱/营养信息管理器,我为一种配料的营养信息指定了一个单独的表格。目前,我已经概述了一些基本属性,即钠、碳水化合物、卡路里和脂肪。在不深入大量细节和尝试添加每一个可能的相关测量值的情况下,我希望用户能够将自己重要的东西添加到数据库中,比如维生素A或铁。我还不太了解数据库建模(我最近才在学校学习如何建模),所以我认为我不希望程序更

我正在为我想要开发的应用程序设计一个数据库结构,我一直想知道如何设计一个实体(我使用的是Chen的符号),以便最终用户可以通过程序界面扩展它

例如,我计划编写的软件是一个食谱/营养信息管理器,我为一种配料的营养信息指定了一个单独的表格。目前,我已经概述了一些基本属性,即钠、碳水化合物、卡路里和脂肪。在不深入大量细节和尝试添加每一个可能的相关测量值的情况下,我希望用户能够将自己重要的东西添加到数据库中,比如维生素A或铁。我还不太了解数据库建模(我最近才在学校学习如何建模),所以我认为我不希望程序更改表,以便向该实体添加新属性。那我该怎么做呢

到目前为止,我的(相当不完整的)模型如下。显然,这里还需要做更多的工作(更不用说这些实体之间的关系了)


假设您的其他属性使用相同的单位,您可以使用两个额外的表来完成

table custom_field
-----------------
id
name

table ingredient_custom_field
----------------------------
id
ingredient_id
custom_field_id
custom_value
这假设自定义字段属于配料。如果你所有的数值都以毫克为单位,那么对于一个给定的配方,将它们汇总起来就相对简单了——好吧,在你开始尝试将液体盎司转换为重量之前,这很简单,但这是另一个问题。 如果您使用的是postgresql,则可以使用json、hstore或其他数据类型将此复杂信息存储在表本身中。
现在,如果您最终拥有一些数字类型,其他类型是标志(无麸质等),那么您将不得不在某种程度上更改设计或将所有内容存储为文本,但将更难对数字结果求和。

假设您的其他属性使用相同的单位,你可以多加几张桌子

table custom_field
-----------------
id
name

table ingredient_custom_field
----------------------------
id
ingredient_id
custom_field_id
custom_value
这假设自定义字段属于配料。如果你所有的数值都以毫克为单位,那么对于一个给定的配方,将它们汇总起来就相对简单了——好吧,在你开始尝试将液体盎司转换为重量之前,这很简单,但这是另一个问题。 如果您使用的是postgresql,则可以使用json、hstore或其他数据类型将此复杂信息存储在表本身中。
现在,如果您最终拥有一些数字类型,其他类型是标志(无麸质等),那么您将不得不在某种程度上更改设计或将所有内容存储为文本,但将更难对数字结果求和。

可能需要用户可扩展数据模型,但它们基本上不是关系型的

您可能对我的演示感兴趣(尽管这些概念适用于任何RDBMS)。以下是摘要:

设计一个可扩展的、灵活的模式来支持用户 定制是一个常见的需求,但很容易自己绘制 陷入一个角落

可扩展数据库要求的示例: -允许用户根据需要声明新字段的数据库。 -或者是包含许多产品的电子商务目录,每个产品都有不同的属性。 -或支持自定义数据扩展的内容管理平台

我们用于满足这些需求的解决方案过于复杂和复杂 表演糟透了。我们应该如何找到正确的平衡 在模式和无模式数据库设计之间

我将简要介绍实体属性值(EAV)的缺点, 一个有问题的设计,这是一个反模式的例子,称为 内部平台效应,即对属性管理进行建模 系统位于RDBMS体系结构之上,该体系结构已经提供 通过列、数据类型和约束的属性

然后我们将讨论替代数据建模的优缺点 模式,在开发人员生产力、数据完整性方面, 存储效率和查询性能,以及易于扩展性

  • 类表继承
  • 序列化BLOB
  • 反向索引

请回复您的评论:

@JoeLove的答案是实体属性值设计。我已经写了其他关于EAV陷阱的答案,或者你可以阅读我的博客

@BennyHill的答案是最好的解决方案,因为它在关系数据库范例中工作,不需要您创建“可扩展”的数据库模式


这个概念被称为多对多关系,例如,一个食谱有许多成分,而每个成分又可以在许多食谱中使用。这方面的关系解决方案是创建一个表来表示这种关系,这样就可以为配方及其成分的每一对插入一行。

可能需要用户可扩展数据模型,但它们基本上不是关系型的

ingredients_nutrients
    id              unsigned int(P)
    ingredient_id   unsigned int(F ingredients.id)
    nutrient_id     unsigned int(F nutrients.id)
    grams           double

+----+---------------+-------------+-------+
| id | ingredient_id | nutrient_id | grams |
+----+---------------+-------------+-------+
|  1 |             1 |           1 |   3.0 |
|  2 |             1 |           2 |  15.3 |
|  3 |             2 |           3 |  20.0 |
| .. | ............. | ........... | ..... |
+----+---------------+-------------+-------+
您可能对我的演示感兴趣(尽管这些概念适用于任何RDBMS)。以下是摘要:

设计一个可扩展的、灵活的模式来支持用户 定制是一个常见的需求,但很容易自己绘制 陷入一个角落

可扩展数据库要求的示例: -允许用户根据需要声明新字段的数据库。 -或者是包含许多产品的电子商务目录,每个产品都有不同的属性。 -或支持自定义数据扩展的内容管理平台

我们用于满足这些需求的解决方案过于复杂和复杂 表演糟透了。我们应该如何找到正确的平衡 在模式和无模式数据库设计之间

我将简要介绍实体属性值(EAV)的缺点, 一个有问题的设计,这是一个
nutrients
    id              unsigned int(P)
    name            varchar(15)
    ...

+----+--------+-----+
| id | name   | ... |
+----+--------+-----+
|  1 | Sodium | ... |
|  2 | Iron   | ... |
|  3 | Fat    | ... |
| .. | ...... | ... |
+----+--------+-----+
recipes
    id              unsigned int(P)
    name            varchar(50)
    ...

+----+-------+-----+
| id | name  | ... |
+----+-------+-----+
|  1 | Pizza | ... |
| .. | ..... | ... |
+----+-------+-----+
recipes_ingredients
    id                  unsigned int(P)
    recipe_id           unsigned int(F recipes.id)
    ingredient_id       unsigned int(F ingredients.id)

+----+-----------+---------------+
| id | recipe_id | ingredient_id |
+----+-----------+---------------+
|  1 |         1 |             1 |
|  2 |         1 |             2 |
| .. | ......... | ............. |
+----+-----------+---------------+