数据库规范化
第一范式(1NF)
定义:第一范式是为了要排除重复组的出现,要求数据库的每一列的论域都是由不可分割的原子值组成;即每个字段的值都只能是单一值。
不满足第一范式的情况:
重复组
交易
顾客 | 日期 | 数量 |
---|---|---|
Pete | Monday | 19.00 -28.20 |
Pete | Wednesday | -84.00 |
Sarah | Friday | 100.00 150.00 -40.00 |
在这个关系中,数量就是重复组。在这种情况下就不符合第一范式。 想要消除重复组的话,只要把每笔记录都转化为单一记录即可:
交易
顾客 | 日期 | 数量 |
---|---|---|
Pete | Monday | 19.00 |
Pete | Monday | -28.20 |
Pete | Wednesday | -84.00 |
Sarah | Friday | 100.00 |
Sarah | Friday | 150.00 |
Sarah | Friday | -40.00 |
缺乏唯一标识符
交易
顾客 | 日期 | 数量 |
---|---|---|
Pete | Monday | 19.00 |
Pete | Monday | 19.00 |
如上所示,这两笔交易可以说是一模一样,也就是说如果只靠这些资料我们没有办法分辨这两笔记录。我们之所以说它不符合第一范式,是因为上面这样的表示法欠缺一个唯一标识符,可以是一个字段,也可以是一组字段,而且可以保证在这个资料中唯一标识符不会重复出现。要将它正规化到符合第一范式的原则只需要加入一个唯一标识符即可:
交易
交易 ID | 顾客 | 日期 | 数量 |
---|---|---|---|
1 | Pete | Monday | 19.00 |
2 | Pete | Monday | 19.00 |
判断第一范式的依据:
第一范式满足每个字段都只包含单一的值,而不是一组值或嵌套的记录。
第二范式(2NF)
定义:在符合第一范式的情况下,要求数据表里的所有非主属性都要和该数据表的主键有完全依赖关系;如果有哪些非主属性只和主键的一部份有关的话,它就不符合第二范式。也可以说2范式消除了非主属性对码的部分函数依赖。
不满足第二范式的情况
组件 ID (主键) | 价格 | 供应商ID (主键) | 供应商名称 | 供应商住址 |
---|---|---|---|---|
65 | 59.99 | 1 | Stylized Parts | VA |
73 | 20.00 | 1 | Stylized Parts | VA |
65 | 69.99 | 2 | ACME Industries | CA |
首先这个关系中的值都是单一值,满足第一范式。并且同一个组件可能有不同的供应商提供,所以这个关系的主键是(组件 ID ,供应商 ID)非主属性是(价格,供应商名称,供应商住址)
判断是否满足第二范式,先看价格是否满足与主键的完全依赖。由于每个组件都有一个组件ID,并且每个组件的价格都受供应商的影响,所以价格确实和主键完全相关(完全依赖)。
另一方面,供应商的名称和住址就只和供应商 ID 有关(部分依赖),这不符合第二范式的原则。
要让关系满足第二范式,就要消除供应商名称和住址对码的部分函数依赖。仔细看就会发现 "Stylized Parts" 这个名称和 "VA" 这个住址重复出现了两次;要是它改名了或是被其他公司并购了怎么办?这时候最好把这些数据独立出新的数据表:
供应商 ID (主键) | 名称 | 住址 |
---|---|---|
1 | Stylized Parts | VA |
2 | ACME Industries | CA |
组件 ID (主键) | 价格 | 供应商 ID(主键、非关键词) |
---|---|---|
65 | 59.99 | 1 |
73 | 20.00 | 1 |
65 | 69.99 | 2 |
判断第二范式的依据:
先判断是否满足第一范式,如果不满足第一范式,那一定不满足第二范式。如果满足第一范式,再判断非主属性对码是否有部分函数依赖,如果存在部分函数依赖则不是第二范式,否则是第二范式。
第三范式(3NF)
定义:所有非主键属性都只和候选键有相关性。也可以说是在满足第二范式的情况下,消除了非主属性之间的传递函数依赖(非主键属性之间应该是独立无关的)
不满足第三范式的情况
元件编号 (主键) | 制造商名称 | 制造商地址 |
---|---|---|
1000 | Toyota | Park Avenue |
1001 | Mitsubishi | Lincoln Street |
1002 | Toyota | Park Avenue |
首先这个关系满足第二范式,每个元件编号都能确定一个制造商名称和一个制造商地址。但我们发现与元件本身比起来,制造商地址应该和制造商名称有关系,存在传递依赖违反了第三范式。
正确做法是,将制造商和制造商地址单独建立一个表:
制造商名称 (主键) | 制造商地址 |
---|---|
Toyota | Park Avenue |
Mitsubishi | Lincoln Street |
元件编号 (主键) | 制造商名称 |
---|---|
1000 | Toyota |
1001 | Mitsubishi |
1002 | Toyota |
判断第三范式的依据:
先判断是否满足第二范式,在满足第二范式的基础上,查看非主属性之间是否存在传递函数依赖,如果存在传递函数依赖则不属于第三范式,否则属于第三范式。
BC范式(Boyce-Codd范式)
定义:是在第三范式的基础上加上稍微更严格约束,每个BCNF关系需满足第三范式。BCNF去除了属性间的不必要的函数依赖。
不满足BC范式的情况
【例】关系模式STJ(S,T,J)中,S表示学生,T表示教师,J表示课程,每一教师只教一门课,每门课有若干教师,某一学生选定某门课就对应一个固定的教师。
从语义可以知道:(S,J)-> T (S,T)-> J T->J
在这个例子中,S,T,J都是主属性,不存在一个非主属性对码的传递函数依赖,所以一定是第三范式。又因为存在一个不必要的函数依赖T->J,这个函数依赖可以由(S,T)-> J分解得到,因此不是BC范式。
那么怎样变成BC范式呢?可以将关系模式STJ分解为ST(S,T)与TJ(T,J)它们都是BCNF
判断BC范式的依据:
先判断是否属于第三范式,检查是否有任何非候选键的属性集可以唯一确定其他任何属性。如果有,那么关系不在BCNF。
参考
- 维基百科-第一正規化
- 维基百科-第二正規化
- 维基百科-第三正規化
- 百度百科-第二范式
- 维基百科-BC正規形式
- 数据库系统概论(第六版)第180页例6.8