我知道要转换为 BCNF,我们需要考虑所有违规行为并根据需要对每个 FD 进行分解。
例如,如果我们有 R(A,B,C,D) 和 FD 的 AB->C, B->D, C->A。我们可以计算每个的闭包,{AB}+ = ABCD,{B}+ = BD,{C}+ = CA。
在通过算法之后,有效分解为 BCNF 将是 R1(B,D)、R2(C,A)、R3(B,C)。
我感到困惑的是,虽然这种分解在算法之后似乎是正确的,但如果第一个函数依赖 AB->C 似乎不被满足,它怎么可能是正确的?
我知道要转换为 BCNF,我们需要考虑所有违规行为并根据需要对每个 FD 进行分解。
例如,如果我们有 R(A,B,C,D) 和 FD 的 AB->C, B->D, C->A。我们可以计算每个的闭包,{AB}+ = ABCD,{B}+ = BD,{C}+ = CA。
在通过算法之后,有效分解为 BCNF 将是 R1(B,D)、R2(C,A)、R3(B,C)。
我感到困惑的是,虽然这种分解在算法之后似乎是正确的,但如果第一个函数依赖 AB->C 似乎不被满足,它怎么可能是正确的?
您产生的分解实际上是正确的,因为分解的模式在 BCNF 中。
但是,正如您已经注意到的那样,它不会保留依赖关系,尤其是依赖关系
AB → C
丢失了。所以你重新发现了关于 BCNF 中分解的一个重要点:在 BCNF 中总是可以分解关系,但代价是有时会丢失一个或多个依赖项。
这在实践中意味着什么?我们可以失去(可能很重要的)约束。在这种情况下,例如,对于每对值
AB
总是有一个值的约束C
不能在结果模式上强制执行。我们可以为此做点什么吗?好吧,我们可以在 3NF 中进行分解,因为用于 3NF 的合成算法可以保证产生始终无损且保留函数依赖关系的分解。例如,在这种情况下,它将产生分解
R1(A B C)
和R2(B D)
,它维护所有依赖关系。但是,等一下!我们现在有一个分解,它不会消除使用 BCNF 算法消除的所有冗余,因为由于依赖关系
C → A
,我们将具有相同的值A
每次我们有一个特定的值C
。所以,我们现在有一个两难选择:我们应该更喜欢保留依赖关系的 3NF 以牺牲一些冗余为代价,还是更喜欢 BCNF 以牺牲一些数据的“意义”为代价减少冗余?
许多人的意见是我们应该选择 3NF,因为数据意义被认为比数据冗余更重要(不仅如此,而且因为 3NF 算法是多项式算法,而 BCNF 算法是指数算法)。