我可以无损地分解这张桌子吗?


10

我偶然发现了一个数据库设计问题,而这个数据库设计问题超出了我的能力范围,而我的DBA专家也开始进行防火训练。

本质上,我有一个带有以下主键的表(为简洁起见,PK):

child_id   integer
parent_id  integer
date       datetime

child_id并且parent_id是实体表的外键。“子”表本身还包含“父”表的外键,并且lo child_id始终引用与parent_id上表所期望的相同的外键。实际上,事实证明,还有一些额外的代码可以使两者保持同步。

这使这位热情洋溢的标准化新手说:“我应该删除冗余!”

我分解为以下内容:

Table_1 PK:
child_id   integer
date       datetime

Table_2 PK:
parent_id  integer
date       datetime

Table_3: (already exists)
child_id   integer PRIMARY KEY
parent_id  integer FOREIGN KEY

而且,当我自然地将这些人加入一起时,我将恢复原始表。据我了解,制造出了5NF。

但是,现在我意识到存在隐藏的业务规则。

通常,与给定日期关联的日期child_id必须是与对应日期关联的日期的子集parent_id。您可以看到第一个表强制执行此规则。

我的分解不会强制执行该规则,因为您可以自由地将其添加到表1中,直到日期变得太大为止。

这将我引向以下问题:

  1. 这是5NF分解吗?虽然我说它允许插入异常,但它似乎也遵循Wiki示例,该示例本身遵循本指南。短语(强调我)“我们可以从由三种不同的记录类型组成的规范化形式中重构所有真实事实”,这给了我一个特殊的停顿,因为无论我注入多少垃圾Table_1,自然连接仍然会忽略它。

  2. 假设我不喜欢这种分解(我不喜欢)。我自由地承认,实际的解决方案是保留表和代码不变。但是,从理论上讲,是否有一种方法可以分解和/或添加约束,以使我摆脱第一个表保留我的业务规则?


1
您原始表中的键是什么?应该满足什么依赖性?您似乎在说child_id-> parent_id,在这种情况下child_id和parent_id不能都成为该表中同一键的一部分。
nvogel 2011年

1
@trevor:您是否曾经在这里查看答案?询问后19分钟最后一次看到。答案稍后出现。
gbn

Answers:


9

归一化基于功能依赖性。功能依赖关系与语义有关。他们与数据的含义有关。当您将一个实际问题简化为“ parent_id,child_id,date”的级别,并且不包含任何样本数据时,您实际上会限制尽职调查的数据库设计人员可以为您提供的帮助。

您在一个表中具有键{child_id,parent_id,date},并且在子表中具有(似乎)唯一对{child_id,parent_id}的事实并不一定意味着部分组合是多余的。这可能意味着在以{child_id,parent_id,date}作为主键的表中,一对属性{child_id,parent_id}应该首先引用子表。

如果是这样,您可以使用FOREIGN KEY (child_id, parent_id) REFERENCES child (child_id, parent_id)。为此,您需要在表“ child”中的一对列(child_id,parent_id)上具有UNIQUE约束,如果child_id是其主键,这应该不是问题。

但是,如果不知道数据的含义,就无法说出来,而且您是该线程中唯一知道这一点的人。(但我们很乐意让您向我们解释。)

就原始表而言,您似乎是在说child_id-> parent_id。如果是这种情况,为什么首先在原始表中使用parent_id?为什么键(child_id,日期)不仅仅带有对“ child”表的外键引用?在我看来,您正在谈论的那种冗余可以通过删除列“ parent_id”来解决。

INSERT语句形式的SQL DDL和示例数据可以帮助我们。DDL和INSERT语句比描述更精确。


1
+2表示“功能依赖”提示
jcolebrand

3

尝试这个...

  • (child_id,parent_id)在子表中添加唯一约束
  • 您的当前表(PK,FK:child_id, PK,FK:parent_id, PK:date)保持不变,FK位于新唯一约束的2列上

要么

  • 从当前子表中删除FK
  • (PK,FK:child_id, FK:parent_id)与孩子创建一个1:1 新表
  • 您当前的表格(PK,FK: child_id, PK,FK: parent_id, PK:date)保持不变。但是FK在新表的2列上

如果没有别的,它可能会启发您...

如果我正确理解,它将删除冗余和代码...

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.