我一直在努力构建一个更抽象的模式,其中有几个表对非常相似的关系进行建模,我只想对“本质”进行建模。由于我正在使用的环境 (Drupal 7),我无法改变问题的性质:相同基本类型的关系可以引用一个角色中对象的两个不同表之一。让我们举一些例子来澄清(这不是我的实际问题领域,而是一个类似的问题)。以下是要求:
首先,如果您不熟悉 Drupal,要点如下:用户在一个表中,所有其他实体在第二个表中(粗略概括,但足够了)。
假设我们要为“工作”关系建模,假设“公司”属于“实体”类型,“主管”属于“用户”类型(“类型”是我的意思那是他们的元组所在的数据库中的表)。以下是简化的要求:
- 用户可以为公司工作
- 一家公司可以为一家公司工作
- 这些“works for”关系应该在同一个表中。
我有两个想法,但都不太符合我目前对架构质量的看法,这就是我想要了解的地方。
- 一个外键列与“类型”列配对
- 两个外键列,总是最多使用一个(恶心!)
如果您是视觉思维者,这里有两个选项代表用户 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/