2

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

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

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

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

我有两个想法,两者都不完全符合我目前对模式质量的态度,这就是我想要了解的地方。

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

如果您是视觉思考者,这里有两个选项表示用户 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 有什么问题,以及在不将“用户”重构为“实体”的约束下,您如何对这种关系建模?

注意: 为此,我对理论纯度比实用解决方案更感兴趣

4

2 回答 2

1

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

采用子/超类型的模式之一。这使用下面列出的关系定义,以及超/子类型约束。这个约束是超类型关系中的每个元组必须与一个子类型元组完全对应。换句话说,子类型必须形成一个不相交的、覆盖超类型的集合。

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

    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 |
    +---------------+-------------+
于 2012-08-31T09:01:48.487 回答
0

选项 1(和选项 2)的问题在于它是一个多值依赖项,因此违反了第四范式。但是,在您给出的限制范围内,您对此无能为力。

如果您可以用worksfor视图替换表,那么您可以将用户-公司和公司-公司关系分开。

在您的两个选择中,选项 2 的优点是可能更容易实施参照完整性,具体取决于您的平台。

在您当前的限制范围内,一个潜在的、如果古怪的、实用的解决方案可能是给公司积极的 ID 和用户消极的 ID,这消除了选项 2 的空列并将选项 1 的类型列变成一个暗示,但我觉得即使建议它也很脏.

同样,如果您不需要知道实体是什么类型,只要您可以通过加入来确定它,那么使用 Guids 作为 ID 将消除对type列的需要

于 2012-08-31T06:09:23.133 回答