第一范式(1NF): 属性不可分
比如表中有一个列叫courses,包含存有学生所选的5门课的名字,以分号分隔, 就不符合1NF。
第二范式(2NF):所有属性必须依赖于主键
比如学生表中主键是StudentId,另外有一列是BookName, BookName逻辑上是不会依赖StudentId的,所以不符合2NF
第三范式(3NF):所有属性不能依赖非主键
比如学生表中主键是StudentId,另外有一列是BookId,还有一列是BookName, BookName逻辑上是依赖BookId的,却被放在学生表中。
第四范式(4NF):去除不相关的多值(多对多)依赖
比如在学生选课的环节中,有一个关系表叫student_course_room, 采用联合主键(studentId,courseId, roomId)。这三者(studentId, courseId, roomId)并不都是直接相关的,比如student和room实际上市通过course联系起来的,因为course被安排在指定的room里进行,学生才知道要了解room的信息。这样如果采用以(studentId,courseId, roomId)为联合主键的关系表student_course_room来记录三者的关系的话,就等于创建了不相关(student-room并不直接相关)的多值依赖,造成数据冗余。
解决方法是把这个3角关系(student-course-room)分为2对关系(student-course和course-room)的关系。
第五范式(5NF):去除相关的多对多依赖
加入4NF中例子里,student和room在现实中时存在关联的(我就见过有的学校的自习室是区分本国学生和留学生的),那么采用student_course_room(studentId, courseId, roomId)的设计的话是不符合5NF,尽管不存在不相关的多值依赖,但是存在相关的多值依赖。解决方法是分解成3对多对多关系(student-course, course-room, student-room).
总的来说范式有以下3规律:
1. 属性只能包含单一的值,不能能包含多值(1NF)
2. 实体中的所有属性都只能是依赖主键而存在的属性(2NF和3NF)
3. 关系中只能有双边关系,不能有多边关系(造成冗余). 也可以认为是关系要尽量细化,粒度尽量小。(4NF和5NF)