1NF 第一范式
关系的每个属性都必须具有原子性,不允许“表中套表”。
:::info
上图这样的表中套表是不允许的。
:::
2NF 第二范式
(满足第一范式的前期下)表中的所有属性能且仅能被所有主键一一对应。
:::info
如上表,S#和C#为学生编号和课程编号,都是主键。
SNAME、AGE、ADDR都可以由S#单独一个主键就对应出来,这是不符合2NF的,只有GRADE是S#和C#两个主键整体才能对应出来,这是符合2NF的。
像这样,存在仅仅被主键的一部分就可以对应出来的属性的表,不符合2NF。
:::
不符合2NF的表存在的问题
插入异常
由于主键不能为空,所以S#与C#在插入数据时不能为null,否则整条数据都无法插入。 :::info 例如,某学生入学后还没选课,那么就不存在C#,这样一来,该学生的姓名年龄住址等属性都会无法插入。 :::
删除异常
由于删除数据时必须删除整条数据,所以当某个属性的所有数据都被删除时,该数据对应的主体的其它数据也会被全部删除。 :::info 例如,假如一个学生入学后因故退掉了全部的课,那么该学生的所有姓名年龄住址等信息都会被删除,但是实际上这个学生并没有被开除。 :::
更新异常
不符合2NF的表会存在大量的数据冗余,因此在更新数据时会很难保证数据一致性。
:::info
例如,一个学生选了100门课,那么就会有100条记录,这些记录中除了GRADE和C#属性不同,其它属性都是重复的,这就造成了数据冗余。
并且,如果要更新学生的住址信息,就得把所有记录的地址信息全部改掉,这实际上是资源的浪费。
:::
3NF 第三范式
(满足第二范式的前提下)表中的属性不应该存在传递依赖。
:::info
如上表,因为EMP#可以决定工资等级SAL_LEVEL,而工资等级又可以决定工资SALARY,所以这里存在一个依赖传递,不符合3NF。
:::
不符合3NF的表存在的问题
插入异常
当某个员工的工资等级未定的时候,无法录入该员工的数据。
删除异常
假如只有一个人的工资等级为3,如果这个员工被开除,那么表中唯一存储了3级工资对应的工资的数据也会被删除,类似于不符合2NF的情况。
更新异常
与不符合2NF的情况类似,会有数据冗余和难以保证数据一致性的问题。
BCNF
(与3NF基本等价,但更严格)如果存在属性1→属性2的决定关系,属性1必须是主键。
:::info
例如下表,C是城市,S是街道,P是邮政编码。主键是S和C。
显然这张表是符合3NF的,但是由于邮政编码可以唯一决定一个城市,但邮政编码又不是一个主键,所以这张表并不符合BCNF范式。
:::
一个表符合NF3但是不是BCNF的情况实际上非常少。
4NF 第四范式
在3NF的情况下,消除属性之间的多值依赖,就得到4NF。
5NF 第五范式
在4NF的情况下,消除连接依赖,就得到5NF。
不符合范式的解决方法
one fact in one place,即一事一地。
:::info
例如上表中学生表可以分解成两张表:
通过两张表的组合,上面的三个异常都不会出现。
:::