在设计关系型数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求就被称为不同的范式,也就是说,范式是符合某一种设计要求的总结。要想设计一个结构合理的关系型数据库,必须满足一定的范式。此外,各种范式呈递次规范,越高的范式数据库冗余越小。满足最低要求的范式是第一范式(1NF)。在第一范式的基础上进一步满足更多规范要求的称为第二范式(2NF),其余范式以次类推。一般说来,数据库只需满足第三范式(3NF)就行了。
本文主要介绍在实际开发中这三种最为常见的范式:
1.第一范式(1NF):(属性的原子性约束--属性不可分解)
第一范式是最基本的范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式。所以,属性下的数据不能是集合,数组,记录等非原子数据项。实体中的某个属性有多个值时,必须拆分为不同的属性。
比如,一个学生选课系统,先设计学生表,内容包括:学号、学生姓名、年龄、性别、课程名称、课程学分、学科成绩、系别、系办地址、系办电话信息。
学号 | 学生姓名 | 年龄 | 性别 | 课程名称 | 课程学分 | 学科成绩 | 系别 | 系办地址 | 系办电话 |
---|---|---|---|---|---|---|---|---|---|
001 | 张三 | 24 | 男 | 《数据结构》 | 4 | 82.0 | 计算机系 | 10号楼 | 123456 |
002 | 李四 | 25 | 女 | 《数据结构》 | 4 | 79.5 | 计算机系 | 10号楼 | 123456 |
003 | 王五 | 25 | 男 | 《数据结构》 | 4 | 85.0 | 计算机系 | 10号楼 | 123456 |
004 | 赵六 | 25 | 男 | 《数据结构》 | 4 | 78.0 | 数学系 | 6号楼 | 456789 |
001 | 张三 | 24 | 男 | 《C语言》 | 3 | 85.0 | 计算机系 | 10号楼 | 123456 |
002 | 李四 | 25 | 女 | 《C语言》 | 3 | 78.0 | 计算机系 | 10号楼 | 123456 |
003 | 王五 | 25 | 男 | 《C语言》 | 3 | 79.5 | 计算机系 | 10号楼 | 123456 |
004 | 赵六 | 25 | 男 | 《C语言》 | 3 | 81.0 | 数学系 | 10号楼 | 456789 |
其实任何复杂的系统,只要数据信息可以发生关联,我们都可以合并设计成一个表结构。但是,这样的数据库表结构设计合理吗?
问题分析:
a、依赖关系:该学生表中,课程学分依赖于课程名称,而不依赖于学号。
b、数据冗余:同一门课程的学分相同,采用该学生表存储数据的话,对相同的课程存储相同的课程学分,会造成数据冗余,浪费存储空间。
c、数据更新异常:若更改某一门课程的学分,则该表中其他所有相同课程的学分都要更改,操作复杂;若需要新增一门课程,因为缺乏其他字段(如学号、学生姓名等)信息,导致数据插入困难。
d、数据删除异常:如果部分学生毕业了,学生记录会随之删除,该表中,删除学生信息同时也会删除课程名称、课程学分等信息,这自然不可取。
为了解决以上问题,我们引入接下来需要介绍的范式。2.第二范式(2NF):(记录的惟一性约束--添加主键,非主键字段都和主键相关)
第二范式在第一范式基础上,要求数据库表中的每个实例或记录必须可以被唯一地区分。比如在学生表中,学号可以唯一确定一个学生,而其他属性对不同的学生而言,有相同的可能。这时,学号就可以作为学生表的主键。此外,第二范式要求:实体的属性完全依赖于主关键字。所谓完全依赖是指不能存在仅依赖主关键字一部分的属性,如果存在,那么这个属性和主关键字的这一部分应该分离出来形成一个新的实体,新实体与原实体之间是一对多的关系。为实现区分通常需要为表加上一个列,以存储各个实例的唯一标识。简而言之,第二范式就是在第一范式的基础上属性完全依赖于主键。
为了解决第一范式表中的问题,我们把学生表和课程表以及选课关系分离,如下所示
学号 | 学生姓名 | 年龄 | 性别 | 系别 | 系办地址 | 系办电话 |
---|---|---|---|---|---|---|
001 | 张三 | 24 | 男 | 计算机系 | 10号楼 | 123456 |
002 | 李四 | 25 | 女 | 计算机系 | 10号楼 | 123456 |
003 | 王五 | 25 | 男 | 计算机系 | 10号楼 | 123456 |
004 | 赵六 | 25 | 男 | 数学系 | 6号楼 | 456789 |
001 | 张三 | 24 | 男 | 计算机系 | 10号楼 | 123456 |
002 | 李四 | 25 | 女 | 计算机系 | 10号楼 | 123456 |
003 | 王五 | 25 | 男 | 计算机系 | 10号楼 | 123456 |
004 | 赵六 | 25 | 男 | 数学系 | 10号楼 | 456789 |
课程名 | 课程学分 |
---|---|
《数据结构》 | 4 |
《C语言》 | 3 |
学号 | 课程名称 | 成绩 |
---|---|---|
001 | 《数据结构》 | 82.0 |
002 | 《数据结构》 | 79.5 |
003 | 《数据结构》 | 85.0 |
004 | 《数据结构》 | 78.0 |
001 | 《C语言》 | 85.0 |
002 | 《C语言》 | 78.0 |
003 | 《C语言》 | 79.5 |
004 | 《C语言》 | 81.0 |
3.第三范式(3NF):(字段冗余性约束--确保每列都和主键列直接相关,而不是间接相关)
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。
我们看第二范式中的学生表,学号作为主关键字,因为存在如下决定关系:
学号 | 学生姓名 | 年龄 | 性别 | 系别 |
---|---|---|---|---|
001 | 张三 | 24 | 男 | 计算机系 |
002 | 李四 | 25 | 女 | 计算机系 |
003 | 王五 | 25 | 男 | 计算机系 |
004 | 赵六 | 25 | 男 | 数学系 |
001 | 张三 | 24 | 男 | 计算机系 |
002 | 李四 | 25 | 女 | 计算机系 |
003 | 王五 | 25 | 男 | 计算机系 |
004 | 赵六 | 25 | 男 | 数学系 |
系别 | 系办地址 | 系办电话 |
---|---|---|
计算机系 | 10号楼 | 123456 |
数学系 | 6号楼 | 456789 |