2.2 第二范式2NF
2NF可以如下描述:不存在属于部分主键的属性。
什么情况下会出现属于部分主键的属性呢?这个没有通用的原则,我们只能举一个例子来说明。
例如:成绩表Score主键是StudentID和CourseID,另外还有两个属性:一个是成绩Grade,一个是StudentName。这里的Grade就是完全由两个主键决定的(标准术语叫做“完全依赖”),而StudentName就只是StudentID的属性(标准术语叫做“部分依赖”),因此这个设计就不符合2NF。
可能有人会问:那我就把StudentID作为主键可不可以?当然是可以的,但这样一来CourseID就又不符合2NF了,因为CourseID不是StudentID的属性。
说了半天了,都是说我们要遵守范式,但是不遵守范式究竟有什么问题呢?
简单的说就是两个问题:冗余(存储、操作)、异常(插不进、删多了)
(1)冗余
一个学生选了很多课,这样StudentName就要重复很多次,因为重复很多次,所以哪天学生改名了,所有的StudentName记录都要更新。
(2)异常
插不进:刚来一个学生,还没有选课(假设所有的课都要选),那么他的StudentName就没有地方记录
删多了:假如学生毕业的,所有的课都学完了,那么所有的记录都删除,这样学生的名字最后也没有地方记录了。
2.3 第三范式3NF
3NF可以这样描述:属性不递归依赖于主键。
什么叫递归依赖呢?简单的就是"A → B → C",那么C就是递归依赖(所谓依赖,简单的讲就是“有关系”了)于A了。
注意:在数据库中,存在这样的关系要求A是主键、B和C不是主键。
下面还是给一个简单的例子:
假定学生关系表为Student(学号, 姓名, 年龄, 所在学院, 学院地点, 学院电话),关键字为单一关键字"学号",因为存在如下决定关系:
(学号) → (姓名, 年龄, 所在学院, 学院地点, 学院电话)
这个数据库是符合2NF的,因为每个学生的这些信息都和学生本人是有关系的,也就是说由学号来决定,但是不符合3NF,因为存在如下关系:
(学号) → (所在学院) → (学院地点, 学院电话)
即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的递归依赖。
它也会存在数据冗余、更新异常、插入异常和删除异常的情况,大家可以根据2NF样例中的分析方法分析。
2.4 其它范式
还有一堆其它范式:BCNF,甚至变态的4NF、5NF
但几乎所有的大侠、大虾、专家都说3NF就足够了,没有必要搞那么多了,所以我也就不想追究了,大家若有兴趣可以自己研究一下。
当然,不是说别人说没用我就不管了,最主要的原因,还是在于范式并不是一个包打天下的绝妙武器,也不是数据库设计的灵丹妙药,也是有自己的局限性的,我们在下一篇文章里面详细阐述。