-
引言
关系型数据库是现在广泛应用的数据库类型,对关系型数据库的设计就是对数据进行组织化和结构化的过程。对于小规模的数据库我们处理起来还是比较轻松地,但是随着数据库规模的扩大我们将发现用户操控数据库的SQL语句将变得笨拙、复杂。更糟糕的是很有可能导致数据不完整,不准确。所以我们有必要将数据设计的更加符合规范。
怎样使我们的数据库更加规范呢,前人总结了三个范式(其实一共有五个,但是一般的数据库只需满足三个就已经很高效了。)
-
主要内容:
注意:斜体字部分为逻辑性语言,不容易理解,但很准确;粗体字部分为通俗语言,容易理解,但有失准确。
l 第一范式(1NF):数据库表中的字段都是单一属性的,不可再分。这个单一属性由基本类型构成,包括整型、实数、字符型、逻辑型、日期型等。
换句话说:能分就分,分到不能分为止!
例1:
原表1
上表中“地点”字段中的值就不符合第一范式。正确的做法应该是把大地点和小地点分开,保持每列的原子性,即不可分割性,如下表:
修改后的表
l 第二范式(2NF):在满足第一范式的基础上,数据库表中不存在非关键字段对任一候选关键字段的部分函数依赖(部分函数依赖指的是存在组合关键字中的某些字段决定非关键字段的情况),也即所有非关键字段都完全依赖于任意一组候选关键字。(另外,所有单关键字的数据库表都符合第二范式,因为不可能存在组合关键字。)
也就是说:
1、 尽可能的使用单关键字吧!
2、 每个表只表述一个事,别傻乎乎的把所有信息都放到一个表里!
例2:
原表2
上表满足第一范式,即每个字段具有不可再分性。但是不满足第二范式。从表可以看出组合关键字为(学号,课程名称),但表中“学分”完全依赖“课程名称”,而“姓名”和“年龄”完全依赖“学号”。也就是说在这一张表里描述了两个事情:学生信息、课程信息。
这样的后果是
(1) 数据冗余:同一门课程由n个学生选修,"学分"就重复n-1次;同一个学生选修了m门课程,姓名和年龄就重复了m-1次。
(2) 更新异常:若调整了某门课程的学分,数据表中所有行的"学分"值都要更新,否则会出现同一门课程学分不同的情况。
(3) 插入异常:假设要开设一门新的课程,暂时还没有人选修。这样,由于还没有"学号"关键字,课程名称和学分也无法记录入数据库。
(4) 删除异常:假设一批学生已经完成课程的选修,这些选修记录就应该从数据库表中删除。但是,与此同时,课程名称和学分信息也被删除了。很显然,这也会导致插入异常。
修改后如下:
学生表
课程表
成绩表
l 第三范式(3NF):在第二范式的基础上,数据表中如果不存在非关键字段对任一候选关键字段的传递函数依赖则符合第三范式。所谓传递函数依赖,指的是如果存在"A → B → C"的决定关系,则C传递函数依赖于A。也就是说表中的字段和主键直接对应不依靠其他的中间字段。
说白了:决定某字段值的必须是主键!
例3:
原表3
可以看出表中的学院地点依赖于学院,学院依赖于学号,学院电话同理。所以这不符合第三范式,这样的结果同样会造成上述不良后果
(1) 数据冗余:同一个“学院”由n个学生,“学院地点”和“学院电话”就重复n-1次。
(2) 更新异常:若调整了某学院的地点,数据表中所有有关行的“学院地点”值都要更新,否则会出现同一学院但是地点却不同的情况。
(3) 插入异常:假设要增加一个新学院,暂时还没有人报考。这样,由于还没有“学号”关键字,相关数据将无法记录入数据库。
(4) 删除异常:假设一批学生已经毕业,这些学生信息记录就应该从数据库表中删除。但是,与此同时,学院、学院地点和学院电话信息也被删除了。很显然,这也会导致插入异常。
修改后如下:
学生表
学院表
结束语:通过运用三个范式可以使你的数据库更加准确、高效。但是在关系数据库中,还有多值依赖,联接依赖的问题,从而提出了第四范式,第五范式等更高一级的规范化要求,那些我们以后再谈。