范式,英文:Normal Form,简称NF。它的由英国关系型数据库鼻祖 E.F.Codd在提出关系型数据库模型后总结出来的一种理论,范式也是关系型数据库的理论基础,也是我们在设计数据库时需要遵守的守则。简言之就是,数据库设计对数据的存储性能,还有开发人员对数据的操作都有莫大的关系。所以建立科学的,规范的的数据库是需要满足一些规范的来优化数据数据存储方式。在关系型数据库中这些规范就可以称为范式。 目前在市面上,有迹可循的范式总共有8种,但是我们目前常用的是前三种,所以也简称为三范式,那么下面我们就来介绍这三大范式。我们可以结合表的实例来进行理解,现在假设有一张职工(staff)表,建表语句如下:
[SQL] 纯文本查看 复制代码 CREATE TABLE `staff` (
`id` INT(11) NOT NULL AUTO_INCREMENT COMMENT '职员编号',
`name` VARCHAR(10) DEFAULT NULL COMMENT '职员名字',
`gender` INT(1) DEFAULT NULL COMMENT '职员性别,1:男,0:女',
`mobile` VARCHAR(30) DEFAULT NULL COMMENT '职员电话',
`postcode` VARCHAR(10) DEFAULT NULL COMMENT '邮编',
`province` VARCHAR(10) DEFAULT NULL COMMENT '省',
`city` VARCHAR(10) DEFAULT NULL COMMENT '市',
`county` VARCHAR(10) DEFAULT NULL COMMENT '区、县',
`deptNo` VARCHAR(10) DEFAULT NULL COMMENT '职员所属部门',
`deptName` VARCHAR(10) DEFAULT NULL COMMENT '职员所属部门名称',
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
下面我们就根据三大范式来分析这张表的存在的问题,及如何更改让它更加的符合三大范式。
1.第一范式:列的原子性
当关系模式R的所有属性都不能在分解为更基本的数据单位时,称R是满足第一范式的,简记为1NF。满足第一范式是关系模式规范化的最低要求,否则,将有很多基本操作在这样的关系模式中实现不了。其实说得明白点,就是数据库表的每一个字段(列)都是单一属性、不可再分的。
例如上面的staff表中有一个字段(mobile)是用来存储职员电话的,但是一般职员都有办公电话和家庭电话两个号码,那么就会出现在这个字段插入的数据会出现多个电话号码,违背了第一范式
所以只要将mobile字段拆分成办公电话(businessPhone)和家庭电话(homePhone)就可以区分开,就能满足第一范式。
第二范式:确保表中的每列都和主键相关,消除部分依赖
在满足第一范式的基础之上,第二范式需要确保数据库表中的每一列都和主键相关,而不能只与主键的某一部分相关(主要针对联合主键而言)。也就是说在一个数据库表中,只能有一个主键,而且主键只能为一个字段,不能是联合主键。
以上面那张职员表(staff)为例,在这张表中一个候选键是{id,mobile,deptNo},而deptName依赖于deptNo,同样 name 依赖于 id,因此不符合第二范式的。为了满足第二范式的条件,可以将这个表拆分成staff、dept、staff_dept、staff_mobile四个表。如下:
其实第二范式就是将有数据冗余的数据表通过表和表之间的外键关联起来,从而减小了数据库的冗余。
第三范式:消除传递依赖,非主属性的依赖
第三范式需要确保数据表中的每一列数据都和主键直接相关,而不能间接相关。举个例子,在设计一个订单数据表的时候,可以将客户编号作为一个外键和订单表建立相应的关系。而不可以在订单表中添加关于客户其它信息(比如姓名、所属公司等)的字段。再以上面的staff表为例,province、city、county依赖于postcode(邮编),而postcode依赖于id,换句话说,province、city、county传递依赖于id,违反了第三范式规则。为了满足第三范式的条件,我们可以再将staff表拆分成staff和address两个表,如下:
总结:
在设计数据库的时候我们要最大程度遵循三范式,当然三范式最大的问题在于查询的时候关联很多表,会导致查询效率很低。所以有些时候基于性能考虑,可以违反三范式,适当的做冗余,达到提高查询效率的目的。不过违反范式是适度的,必须为这种做法提供充分的理由。
|