何时为同一字段添加另一个查找表

Tia*_*tos 5 database-design

例子

  • Table Recipe 使用查找表来查找 Recipe Category;
  • Table Ingredient 使用 Ingredient Category 的查找表;
  • 它们处于多对多关系;
  • 配方类别不会用作成分类别,反之亦然;

它应该是单独的查找表,还是我可以使用一个带有额外列的表来确定它是成分还是配方类别?这会影响优化或查询速度吗?

如果单表大约有 100 条记录;分隔的表是 5 和 95。该表将在同一个查询中出现两次以上。

我测试了相关问答关系表中的想法,内容相同,自定义解决方案。在前端和内务处理方面更容易处理数据,但如果数据库增长,数据完整性可能会成为一个问题。

澄清

  1. 一个配方可以按多个配方类别进行分类
  2. 一种成分可以按多个成分类别进行分类
  3. 业务领域有5个菜谱类别
  4. 业务领域有95个成分类别
  5. 具体食谱类别的三个示例是 Omivorous、Vegetarian、Vegan。
  6. 具体成分类别的三个示例是谷物、肉类、鱼类。

我一直在测试这两种解决方案,但由于记录太少,我看不到任何性能改进或损失。此外,在构建前端时,使用一个模型和一个列比使用 2 个模型更容易,但这是一个小问题。

Stack Overflow 上的相关问答:一个查找表还是多个查找表?

MDC*_*CCL 6

虽然RecipeCategoryIngredientCategory有非常相似的名称和属性,它们实际上是两个不同的实体类型,因为他们每个人(一)带有特定的业务领域的含义,(b)的不同种类的关系,以及(c)需要一组特定的规则.

在这一点上,如果目的是实现一个关系型数据库(RDB),这是相当有帮助的执行感兴趣的业务领域的分析(为了构建一个概念性的实体类型的术语(即模型)类型原型实体出现在表,列的条款和约束(点对应于思维之前),它们的属性和相互关系的逻辑模型)。以这种方式进行,更容易准确地捕获业务领域的含义,然后将其反映在实际的 RDB 结构中。

业务领域规则

配方和配方类别

让我们开始使用两种实体类型:RecipeRecipeCategory。在所讨论的场景中,确认以下内容似乎是合理的:

  • 一个食谱是由零一或一对多分类RecipeCategories
  • 一个RecipeCategory进行分类零一或一对多的食谱

这种情况表明,是的,RecipeRecipeCategory涉及多对多(M:N)关系,这意味着存在关联实体类型,我将调用RecipeCategorization.

成分和成分类别

然后,让我们处理IngredientIngredientCategory。在这种情况下,我们可以确认:

  • 一个成分按零一或多个成分分类
  • 一个IngredientCategory组零一或一对多成份

这意味着RecipeRecipeCategory在另一个 M:N 关系中连接,这意味着存在另一个关联实体类型,我将其命名为IngredientCategorization

RecipeCategory 和 IngredientCategory

如上所述,可以观察到 的具体出现RecipeCategory意味着(直接)与 的特定实例相关联Recipe,而不是与 的出现相关联Ingredient。以同样的方式, 的具体实例IngredientCategory旨在(直接)与 的具体出现相关联Ingredient,而不是与 的实例相关联Recipe。因此,RecipeCategoryIngredientCategory是不同的实体类型,需要各自单独考虑。

配方和成分

最后,我们可以假设:

  • 一个配方包括一对多的成分
  • 一种成分包含在零一或多食谱中

因此,还有另一个 M:N 关系,这一次在Recipe和之间Ingredient,它揭示了其他关联实体类型的存在,我将赋予RecipeListing

说明性 IDEF1X 模型

然后,根据上述分析和随后的公式,我创建了 IDEF1X 模型,如图 1所示:

图 1 - 配方简化 IDEF1X 模型

所证明,每个实体类型是在其对应的各个描绘,并显示直接相关于(i)其自身的属性,包含在相应的,以及(ii)该应用的实体类型,由所述的方式关系线.

当然,还有其他间接关系应该通过这里公开的直接连接导出。

逻辑和物理元素

一旦我们分析和定义了重要事物的相关类型,就该确定如何通过数学关系(如果在某个 SQL 数据库管理系统上创建,则声明和可视化为表格)来管理它们的结构域(描绘成)和元组(描绘为)。

由于关系是抽象资源,关系范式的创始人EF Codd 博士设想了以表格形式表示它们的效用,例如,RDB 的用户和实现者可以以更熟悉的方式处理它们。在这方面,即使关系表具有具体的形状,它仍然是给定数据库的逻辑元素,其组件,例如列、行和约束也是逻辑的。

在这方面,将逻辑元素与物理元素区分开来非常重要且具有巨大的实用价值。例如,在文件系统中,物理记录可以由零个、一个或多个字段组成。在 RDB 的情况下,逻辑元素可以由一个或多个物理单元(在较低的抽象级别)提供服务,例如,索引记录页面范围等。

因此,根据上面详述的要点,作为逻辑级别组件的表没有字段(这很可能是支持表声明的底层具体脚手架的一部分,但在物理级别工作)。

说明性逻辑 SQL-DDL 结构

话虽如此,并且基于之前介绍的 IDEF1X 模型,RecipeCategoryIngredientCategory(以及其他已识别的实体类型)都需要一个单独的表来代表它们中的每一个,如下面的 DDL 结构所示:

-- You have to determine which are the most fitting 
-- data types and sizes for all your table columns 
-- depending on your business context characteristics.

-- Also, you should make accurate tests to define the
-- most convenient physical implementation settings; e.g.,
-- a good INDEXing strategy based on query tendencies.

-- As one would expect, you are free to make use of 
-- your preferred (or required) naming conventions. 

CREATE TABLE RecipeCategory ( -- Plays a ‘look-up’ role.
    RecipeCategoryCode CHAR(2)  NOT NULL,  -- This column can retain the values: ‘O’ for ‘Omnivorous’; ‘VT’ for ‘Vegetarian’; ‘VG’ for ‘Vegan’; etc.
    Name               CHAR(30) NOT NULL,
    Description        CHAR(60) NOT NULL,
    Etcetera           CHAR(30) NOT NULL,
    CreatedDateTime    DATETIME NOT NULL,
    CONSTRAINT RecipeCategory_PK  PRIMARY KEY (RecipeCategoryCode),
    CONSTRAINT RecipeCategory_AK1 UNIQUE      (Name),       -- ALTERNATE KEY.
    CONSTRAINT RecipeCategory_AK2 UNIQUE      (Description) -- ALTERNATE KEY.      
);

CREATE TABLE Recipe (
    RecipeNumber    INT      NOT NULL,
    Name            CHAR(30) NOT NULL,
    Description     CHAR(60) NOT NULL,
    Etcetera        CHAR(30) NOT NULL,
    CreatedDateTime DATETIME NOT NULL,      
    CONSTRAINT Recipe_PK  PRIMARY KEY (RecipeNumber),
    CONSTRAINT Recipe_AK1 UNIQUE      (Name),       -- ALTERNATE KEY.
    CONSTRAINT Recipe_AK2 UNIQUE      (Description) -- ALTERNATE KEY.      
);

CREATE TABLE RecipeCategorization ( -- Represents an associative entity type.
    RecipeNumber       INT      NOT NULL,
    RecipeCategoryCode CHAR(2)  NOT NULL, -- Contains meaningful and readable values.
    Etcetera           CHAR(30) NOT NULL,
    ClassifiedDateTime DATETIME NOT NULL,      
    CONSTRAINT RecipeCategorization_PK                   PRIMARY KEY (RecipeNumber, RecipeCategoryCode), -- Composite PK.
    CONSTRAINT RecipeCategorization_to_Recipe_FK         FOREIGN KEY (RecipeNumber)
        REFERENCES Recipe (RecipeNumber),
    CONSTRAINT RecipeCategorization_to_RecipeCategory_FK FOREIGN KEY (RecipeCategoryCode)
        REFERENCES RecipeCategory (RecipeCategoryCode)       
);    

CREATE TABLE IngredientCategory ( -- Plays a ‘look-up’ role.
    IngredientCategoryNumber INT      NOT NULL,
    Name                     CHAR(30) NOT NULL,
    Description              CHAR(60) NOT NULL,
    Etcetera                 CHAR(30) NOT NULL,
    CreatedDateTime          DATETIME NOT NULL,
    CONSTRAINT IngredientCategory_PK  PRIMARY KEY (IngredientCategoryNumber),
    CONSTRAINT IngredientCategory_AK1 UNIQUE      (Name),       -- ALTERNATE KEY.
    CONSTRAINT IngredientCategory_AK2 UNIQUE      (Description) -- ALTERNATE KEY.      
);

CREATE TABLE Ingredient (
    IngredientNumber INT      NOT NULL,
    Name             CHAR(30) NOT NULL,
    Description      CHAR(60) NOT NULL,
    Etcetera         CHAR(30) NOT NULL,
    CreatedDateTime  DATETIME NOT NULL,
    CONSTRAINT Ingredient_PK  PRIMARY KEY (IngredientNumber),
    CONSTRAINT Ingredient_AK1 UNIQUE      (Name),       -- ALTERNATE KEY.
    CONSTRAINT Ingredient_AK2 UNIQUE      (Description) -- ALTERNATE KEY.      
);

CREATE TABLE IngredientCategorization ( -- Stands for an ssociative entity type.
    IngredientNumber         INT      NOT NULL,
    IngredientCategoryNumber INT      NOT NULL,
    Etcetera                 CHAR(30) NOT NULL,
    GroupedDateTime          DATETIME NOT NULL,      
    CONSTRAINT IngredientCategorization_PK                       PRIMARY KEY (IngredientNumber, IngredientCategoryNumber), -- Composite PK.
    CONSTRAINT IngredientCategorization_to_Ingredient_FK         FOREIGN KEY (IngredientNumber)
        REFERENCES Ingredient (IngredientNumber),
    CONSTRAINT IngredientCategorization_to_IngredientCategory_FK FOREIGN KEY (IngredientCategoryNumber)
        REFERENCES IngredientCategory (IngredientCategoryNumber)        
);

CREATE TABLE IngredientListing ( -- Denotes an associative entity type
    RecipeNumber     INT      NOT NULL,
    IngredientNumber INT      NOT NULL,
    Etcetera         CHAR(30) NOT NULL,
    IncludedDateTime DATETIME NOT NULL,      
    CONSTRAINT IngredientListing_PK               PRIMARY KEY (RecipeNumber, IngredientNumber), -- Composite PK.
    CONSTRAINT IngredientListing_to_Recipe_FK     FOREIGN KEY (RecipeNumber)
        REFERENCES Recipe (RecipeNumber),
    CONSTRAINT IngredientListing_to_Ingredient_FK FOREIGN KEY (IngredientNumber)
        REFERENCES Ingredient (IngredientNumber)     
);

--
--
Run Code Online (Sandbox Code Playgroud)

通过这样的结构,您可以防止歧义及其所有逻辑和务实的影响。你避免混淆

  1. 在单个“共享”表中表示多种实体类型,以及
  2. 每个属性的含义和意图(在“共享”列中),

这允许通过 FOREIGN KEY (FK) 约束更轻松地限制其相应的值域和后续引用。查询和结果集变得更加清晰,因为每个方面都是分开处理的。

因此,这种结构本身有助于精确反映所考虑的业务上下文,与概念分析中界定的特征保持一致,并保证数据(行形式的每个断言)符合业务规则。

关于 RecipeCategory 表的实际考虑

考虑到该RecipeCategory表应该 (1) 履行查找角色并且 (2) 只包含几行,我认为PRIMARY KEY在保留值的列上使用 (PK) 约束声明它会非常有利是有意义的,同时,物理上又,即类型CHAR(2)或可能CHAR(3)。所以它可能包括,例如,后面的行:

+————————————————————-+-———————————-+-——————————————— ———————————-+-————-+-————-+
| 食谱类别代码| 姓名       | 说明               | 等等… | 创… |
+————————————————————-+-———————————-+-——————————————— ———————————-+-————-+-————-+
| 哦| 杂食性 | 类别的食谱... | …… | …… |
+--------------------+------------+-------------- ------------+------+------+
| VT | 素食 | 类别的食谱... | …… | …… |
+--------------------+------------+-------------- ------------+------+------+
| VG | 素食 | 类别的食谱... | …… | …… |
+--------------------+------------+-------------- ------------+------+------+
| F | 福 | 类别的食谱... | …… | …… |
+--------------------+------------+-------------- ------------+------+------+
| 乙 | 酒吧 | 类别的食谱... | …… | …… |
+--------------------+------------+-------------- ------------+------+------+

以这种方式,当这样的 PK 列RecipeCategorization作为具有 FK 约束的列“迁移”到表时,它将具有保持其含义和意图的稳定值,从而使结果集INT比值更具可读性,例如,肯定可以帮助解释通过例如派生表(通过 SELECT 语句或 VIEW 定义取回的表)获得的信息。

所有这些仍然与Codd 博士于 1970 年发表的关系模型††的精神一致,他在其中包括以下相关注释:

自然地,对于放入计算机系统和从计算机系统中检索的任何数据,如果用户了解数据的含义,他通常会更有效地使用数据。

关系数据库和应用程序

下面引用的问题摘录与 (a) 所讨论的数据库和 (b) 将与其一起工作的应用程序(应用程序)之间的“链接”除其他外,还必须这样做:

我测试了相关问答关系表中的想法,内容相同,自定义解决方案。在前端和内务处理方面更容易处理数据,但如果数据库增长,数据完整性可能会成为一个问题。

适时指出,就其本质和性质而言,数据是一种非常有价值的组织资产;因此,它必须如此管理。这种基本资源往往比应用程序、应用程序开发平台和编程范式更长寿。

有了这个,RDB 应该是一个独立的(自我保护、自我描述等)软件组件,能够被多个应用程序共享,并且它不能“耦合”——使用面向对象编程的说法——与任何这些应用程序的代码。

因此,您应该 (a) 通过关系理论提供的工具、建模平台和选择的 SQL 系统来管理数据,以及 (b)使用相关应用程序塑造和实施相关流程和图形用户界面开发工具。这样,所有的软件组件就会和谐地工作;它们将是独立的,但同时又是相互关联的。


尾注和参考

信息建模集成定义( IDEF1X ) 是一种非常值得推荐的数据建模技术,美国国家标准与技术研究院(NIST)于 1993 年 12 月将其确立为标准。它完全基于 (a) EF Codd 博士撰写的一些早期关系模型工作;关于 (b)实体关系视图,由PP Chen 博士开发;以及 (c) 逻辑数据库设计技术,由 Robert G. Brown 创建。

††科德,英孚(1970 年 6 月)。大型共享数据库的数据关系模型, ACM 通讯,第 13 卷第 6 期(第 377-387 页)。纽约,纽约,美国。