数据库范式如何判断 数据库范式判断

那天在一家咖啡厅,我看到邻桌的两个程序员正在争论数据库范例。
一个人说:“你看,这张客户信息表里,姓名、电话、地址都是分开的,这是第二范式。
”另一个反驳道:“不,这还不够。
电话号码和地址可以进一步细分,它一定是第三范式。
”我听着,突然想到:这不就是在组织自己的生活吗?东西不能随意放置,必须分类分层才能保持井井有条。
等等,还有一件事。
我书架上的书是按作者姓名的字母顺序排列的。
你不觉得这有点典型吗?

怎么判断属于几范式啊?

说实话,当我们谈论范式时,最麻烦的就是符号和字母,但说白了,无非就是几个要点:不能重复列、不能部分依赖、不能传递依赖。
让我们一步步来看。

比如你给我的R(x,y,z)和F1 (xy→z)看似简单,但里面有很多技巧。
你能先告诉我xy→z是什么意思吗?这意味着 x 和 y 一起可以确定 z,但 x 或 y 单独不能确定。
我也遇到过类似的情况。
例如,订单形式中,订单号+产品编号可以唯一确定金额,但单独的订单号则不能确定金额。

先看1 NF。
简单来说,第一范式意味着列不能有重复值。
例如,订单表中不能有两个金额对应于同一订单号。
你给出的xy → z 例子,如果x、y、z都是简单属性,没有组合,那么它自然满足1 NF。
公平地说,大多数表都能满足1 NF,特别复杂的多列键组合很少见。

然后是2 NF。
它必须满足1 NF并消除非主键属性对某些主键的依赖。
例如,主键是(x,y)。
如果 z 仅取决于 x 或 y,则违反了 2 NF。
在 xy → z 示例中,如果 x 和 y 都是主键的一部分,则 z 不依赖于任何部分键,仅依赖于完整键 (xy),因此在此示例中 xy → z 满足 2 NF。
上次编辑库存表时,我发现库存只基于产品ID,而不是订单ID。
结果发现它违反了2 NF,所以我就把它分开了。

再看一遍3 NF。
它必须满足2 NF并消除非主键属性之间的传递依赖。
例如,x→y,y→z,但x并不直接→z。
在你的例子中,xy→z,这显然是一个直接依赖并且没有被传递,所以它满足3 NF。
我见过一些比较复杂的,比如员工表中,员工ID→部门ID,部门ID→部门地址,但是员工ID并不是直接→部门地址,所以这个需要细分。

最后BCNF。
它比 3 NF 更强大,并且需要任何重要的函数依赖关系才能在左侧有一个超级键。
说白了,这意味着消除所有重要的依赖关系。
在你的 xy → z 例子中,如果 x 和 y 没有覆盖所有候选键,那么它可能不是 BCNF。
但如果 (xy) 是候选键,那么它满足 BCNF。
上次我遇到了BCNF问题。
(A,B)是表中的一个键,但C只依赖于A。
我发现(A,C)也是一个候选键,最终不得不拆表。

4 NF要求更高,需要消除多值依赖。
这通常需要具体的例子。
你的例子中只有一种函数依赖,4 NF 肯定能满足它。

困难其实不在于定义,而在于判断本身。
比如表(A,B,C)中有一个key,但是D只依赖于A,E只依赖于B,F依赖于(A,B),这个时候你就应该看清楚了。
BCNF要求所有依赖项的左边都是超级键,所以D和E必须分开列出,F也要看情况。
当我在做一个项目时,我发现了一堆这样的依赖关系,我花了很长时间画了一个维恩图来对它们进行排序。

总之,判断范式必须根据条件,不能想当然。
在 xy → z 示例中,如果 x 和 y 是候选键的一部分,则它满足 BCNF。
但如果 x 和 y 不是完整键,则 BCNF 可能无法满足。
数据模型中有很多细节。