第一范式(1NF):属性不可分
在前面我们已经介绍了属性值的概念,我们说,它是“不可分的”。而第一范式要求属性也不可分。那么它和属性值不可分有什么区别呢?给一个例子:name | address | age |
小明 | 山东省济宁市 | 13 |
小红 | 辽宁省大连市 | 12 |
表中的address属性实际上的可分的
这种情况不满足第一范式。不满足第一范式的数据库,不是关系数据库!所以,我们在任何关系数据库管理系统中,做不出这样的“表”来。
第二范式(2NF):符合1NF,并且,非主属性完全依赖于码。
听起来好像很神秘,其实真的没什么。一 个候选码中的主属性也可能是好几个。如果一个主属性,它不能单独做为一个候选码,那么它也不能确定任何一个非主属性。给一个反例:我们考虑一个小学的教务管理系统,学生上课指定一个老师,一本教材,一个教室,一个时间,大家都上课去吧,没有问题。那么数据库怎么设计?(学生上课表)
姓名 | 课程 | 老师 | 职称 | 教材 | 教室 | 时间 |
小明 | 数学上 | 老王 | 讲师 | 数学1 | 120 | 8:00 |
一个学生上一门课,一定在特定某个教室。所以有(学生,课程)->教室
一个学生上一门课,一定是特定某个老师教。所以有(学生,课程)->老师
一个学生上一门课,他老师的职称可以确定。所以有(学生,课程)->老师职称
一个学生上一门课,一定是特定某个教材。所以有(学生,课程)->教材
一个学生上一门课,一定在特定时间。所以有(学生,课程)->上课时间
因此(学生,课程)是一个码(联合主键)。
然而,一个课程,一定指定了某个教材,那么就有课程->教材。(学生,课程)是个码,课程却决定了教材,这就叫做不完全依赖,或者说部分依赖。出现这样的情况,就不满足第二范式!
不满足第二范式会产生以下问题:
1、要新增加一门课程叫“微积分”,教材是《大学数学》,怎么办?学生还没选课,而学生又是主属性,主属性不能空,课程无法记录(插入异常)
2、下学期没学生学数学1了,要学数学2,那么表中将不存在课程数学上,也就没了数学1。(删除异常)
3、若要更换课程教材,如果有10000人选课,则要修改10000条数据(修改异常)
解决方法:
将上面的表分成两张表:
学生选课
姓名 | 课程 | 老师 | 职称 | 教室 | 时间 |
小明 | 数学上 | 老王 | 讲师 | 120 | 8:00 |
课程表
课程 | 教材 |
数学上 | 数学1 |
第三范式(3NF):符合2NF,并且,消除传递依赖
上面的学生选课表符合第二范式,但不符合第三范式,原因就在于职称这个属性有传递依赖。
因为职称不依赖与主键,而仅仅依赖于老师,而老师依赖于主键,这就产生的传递依赖。
这会产生以下问题:
1、老师升级了,变教授了,要改数据库,表中有N条,改了N次……(修改异常)
2、没人选这个老师的课了,老师的职称也没了记录……(删除异常)
3、新来一个老师,还没分配教什么课,他的职称无法记录?……(插入异常)
那应该怎么解决呢?和上面一样,再分成两个表:
姓名 | 课程 | 老师 | 教室 | 时间 |
小明 | 数学上 | 老王 | 120 | 8:00 |
老师 | 职称 |
老王 | 讲师 |