sql - 架构设计 : to-one foreign relation with heterogeneous type (different targets), 但角色相同

标签 sql database database-design relational-database normalization

我一直在努力构建一个更抽象的模式,其中有几个表对非常相似的关系进行建模,我只想对“本质”进行建模。由于我正在使用的环境 (Drupal 7),我无法改变问题的性质:相同基本类型的关系可以引用一个角色中对象的两个不同表之一。让我们举一些例子来澄清(这不是我的实际问题领域,而是一个类似的问题)。以下是要求:

首先,如果您不熟悉 Drupal,要点如下:用户在一个表中,所有其他实体在第二个表中(粗略概括,但足够了)。

假设我们要为“工作”关系建模,假设“公司”属于“实体”类型,“主管”属于“用户”类型(“类型”是我的意思那是他们的元组所在的数据库中的表)。以下是简化的要求:

  1. 用户可以为公司工作
  2. 一家公司可以为一家公司工作
  3. 这些“works for”关系应该在同一个表中。

我有两个想法,但都不太符合我目前对架构质量的看法,这就是我想要了解的地方。

  1. 一个外键列与“类型”列配对
  2. 两个外键列,总是最多使用一个(恶心!)

如果您是视觉思维者,这里有两个选项代表用户 123 和 632 以及实体 123 都为实体 435 工作:

  Option 1
+---------------+-------------+---------------+-------------+
| employment_id | employee_id | employee_type | employer_id |
+---------------+-------------+---------------+-------------+
|             1 |         123 |          user |         435 |
+---------------+-------------+---------------+-------------+
|             2 |         123 |        entity |         435 |
+---------------+-------------+---------------+-------------+
|             3 |         632 |          user |         435 |
+---------------+-------------+---------------+-------------+

  Option 2
+---------------+------------------+--------------------+-------------+
| employment_id | employee_user_id | employee_entity_id | employer_id |
+---------------+------------------+--------------------+-------------+
|             1 |              123 |             <NULL> |         435 |
+---------------+------------------+--------------------+-------------+
|             2 |           <NULL> |                123 |         435 |
+---------------+------------------+--------------------+-------------+
|             3 |              632 |             <NULL> |         435 |
+---------------+------------------+--------------------+-------------+

关于选项 1 的想法:我喜欢 employee_id 列具有具体作用,但我鄙视它具有不明确的目标。选项 2 的角色不明确(哪一列是员工?),但对于任何给定的 FK 都有具体的目标,所以我可以这样想:

+-----------+-----------+----------+
|           |         ROLE         |
|           | ambiguous | concrete |
+-----------+-----------+----------+
| T         |           |          |
| A  ambig. |           |     1    |
| R         |           |          |
| G  -------+-----------+----------+
| E         |           |          |
| T  concr. |     2     |     ?    |
|           |           |          |
+-----------+-----------+----------+

选项二对我的项目有非常实用的好处,但我对这么多空值感到不舒服(你甚至可能不称它为 1NF!)

所以这就是我对 SO 的问题的症结所在:如何改进选项 1,否则我可能有什么知识差距让我感到不安?虽然我想不起它违反的具体规则,但设计显然不符合规范化的意图(需要两列来唯一标识关系对我没有任何好处防止异常)。

我明白理想的解决方案是重新设计用户实体,使其相同我一直称之为“实体” "在这里,但请考虑这一点/间接情况(或者至少让我们准确地为这个问题画一条实用线)。

同样,基本问题:就规范化而言,模式选项 1 有什么问题,以及在不将“用户”重构为“实体”的约束条件下,您如何对这种关系建模?

注意: 对此,我更感兴趣的是理论上的纯粹性,而不是实用的解决方案

最佳答案

正如@podiluska 所说,您提出的解决方案违反了第四范式。如果将其重铸为以下形式,则解决方案将消除这一困难并处于 5NF(甚至 6NF?)。

采用子/父类(super class)型的模式之一。这使用下面列出的关系定义,加上超/子类型约束。这个约束是父类(super class)型关系中的每个元组必须精确对应一个子类型元组。换句话说,子类型必须在父类(super class)型上形成一个不相交的覆盖集。

我怀疑在真实情况下的性能可能需要一些重调:

    Table: Employment
    +---------------+-------------+
    | employee_id   | employer_id |
    +---------------+-------------+
    |             1 |         435 |
    +---------------+-------------+
    |             2 |         435 |
    +---------------+-------------+
    |             3 |         435 |
    +---------------+-------------+
    Table: Employee (SuperType)
    +---------------+
    | employee_id   |
    +---------------+
    |             1 |
    +---------------+
    |             2 |
    +---------------+
    |             3 |
    +---------------+
    Table: User employee (SubType)
    +---------------+-------------+
    | employee_id   | user_id     |
    +---------------+-------------+
    |             1 |         123 |
    +---------------+-------------+
    |             3 |         632 |
    +---------------+-------------+
    Table: Entity employee (SubType)
    +---------------+-------------+
    | employee_id   |   entity_id |
    +---------------+-------------+
    |             2 |         123 |
    +---------------+-------------+

关于sql - 架构设计 : to-one foreign relation with heterogeneous type (different targets), 但角色相同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12209328/

相关文章:

database - 一对多对多

mysql - 使用多列子查询优化查询

MySQL 多列匹配多行结果

c# - 彩票入场方式

MySQL 查询数据库中特定用户的连接+计数

mysql - 关于我的 Deck Builder 数据库的建议

database - Django 的历史性

c# - 数据库:如何对 GUID 进行排序?

sql - 已提交读隔离级别是否会导致死锁(Sql Server)?

SQL - 将数据转换为日期/源/值 "grid"