数据库三范式
数据库三范式
关系型数据库是现在广泛应用的数据库类型,对关系型数据库的设计就是对数据进行组织化和结构化的过程。数据库的设计范式是数据库设计所需要满足的规范。只有理解数据库的设计范式,才能设计出高效率、优雅的数据库,否则可能会设计出错误的数据库.
目前,主要有六种范式:第一范式、第二范式、第三范式、BC范式、第四范式和第五范式。满足最低要求的叫第一范式,简称1NF。在第一范式基础上进一步满足一些要求的为第二范式,简称2NF。其余依此类推。
范式可以避免数据冗余,减少数据库的空间,减轻维护数据完整性的麻烦,但是操作困难,因为需要联系多个表才能得到所需要数据,而且范式越高性能就会越差。要权衡是否使用更高范式是比较麻烦的,一般在项目中,满足第三范式就足够了,性能好而且方便管理数据。
函数依赖,如果一个表中某一个字段Y的值是由另外一个字段或一组字段X的值来确定的,就称为Y函数依赖于X。
第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。
1NF是关系模式应具备的最起码的条件,如果数据库设计不能满足第一范式,就不称为关系型数据库。关系数据库设计研究的关系规范化是在1NF之上进行的。
例如(学生信息表):
学生编号 | 姓名 | 姓别 | 联系方式 |
20080901 | 张三 | 男 | email:zs@126.com,phone:88886666 |
20080902 | 李四 | 男 | email:ls@126.com,phone:66668888 |
以上的表就不符合,第一范式:联系方式字段可以再分,所以变更为正确的是:
学生编号 | 姓名 | 性别 | telphone | |
20080901 | 张三 | 男 | zs@126.com | 88886666 |
20080902 | 李四 | 男 | ls@126.com | 66668888 |
第二范式(2NF):在满足第一范式的基础上,数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。(另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。)
上表满足第一范式,即每个字段具有不可再分性。但是不满足第二范式。从表可以看出组合关键字为(学号,课程名称),但表中“学分”完全依赖“课程名称”,而“姓名”和“年龄”完全依赖“学号”。也就是说在这一张表里描述了两个事情:学生信息、课程信息。
这样的后果是
(1) 数据冗余:同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
(2) 更新异常:若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
(3) 插入异常:假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
(4) 删除异常:假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
修改后如下:
学生表
课程表
成绩表
第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。也就是说表中的字段和主键直接对应不依靠其他的中间字段。
说白了:决定某字段值的必须是主键!
可以看出表中的学院地点依赖于学院,学院依赖于学号,即出现了传递依赖。学院电话同理。所以这不符合第三范式,这样的结果同样会造成下述不良后果
(1) 数据冗余:同一个“学院”由n个学生,“学院地点”和“学院电话”就重复n-1次。
(2) 更新异常:若调整了某学院的地点,数据表中所有有关行的“学院地点”值都要更新,否则会出现同一学院但是地点却不同的情况。
(3) 插入异常:假设要增加一个新学院,暂时还没有人报考。这样,由于还没有“学号”关键字,相关数据将无法记录入数据库。
(4) 删除异常:假设一批学生已经毕业,这些学生信息记录就应该从数据库表中删除。但是,与此同时,学院、学院地点和学院电话信息也被删除了。很显然,这也会导致插入异常。
修改后如下:
学生表
学院表
简单的说,
第一范式就是原子性,字段不可再分割;
第二范式就是完全依赖,没有部分依赖;
第三范式就是没有传递依赖。