以前建数据库只是单纯的存取数据,嵌入式设备数据量比较小,也不会去考虑数据冗余的问题。后来在一次面试过程中,我陈述完项目后,面试官问我,你的数据库结构满足第几范式啊?我瞬间就懵了,范式是啥?想想也是醉了。
数据库的这三大范式是为了处理数据冗余、构建比较严谨的数据库结构,设计数据库时必须遵循一定的规则。在关系型数据库中这种规则就称为范式。
下面就来说说三大范式:
1.第一范式1NF(域的原子性)
第一范式是对域的原子性的一个要求,在数据库设计中,一般都应该满足第一范式。如果数据库表中的所有字段值都是不可分解的原子值,就说明该数据库表满足了第一范式,不过有些关系模型中突破了第一范式的限制,这种称为非第一范式的关系模型。换句话说,是否必须满足第一范式的最低需求,主要依赖所使用的关系模型。
例如:我们建一张学生信息表。
表一
学 号 | 姓名 | 性别 | 年龄 | 学 院 | 班 级 | 地址 |
100101 | 张三 | 男 | 18 | 文史 | 1年1班 | 山东省济南市历城区花园路2号 |
100202 | 李四 | 女 | 19 | 农学院 | 1年3班 | 福建省福州市晋安区爱乡园3号 |
100303 | 王五 | 男 | 21 | 医学院 | 4年1班 | 山西省太原市小店区兴武小区3栋 |
100404 | 赵六 | 男 | 20 | 英语 | 3年2班 | 江苏省徐州市泉山区解放路21号 |
学 号 | 姓名 | 性别 | 年龄 | 学 院 | 班 级 | 省份 | 市(县区) | 详细地址 |
100101 | 张三 | 男 | 18 | 文史 | 1年1班 | 山东 | 济南市 | 历城区花园路2号 |
100202 | 李四 | 女 | 19 | 农学院 | 1年3班 | 福建 | 福州市 | 晋安区爱乡园3号 |
100303 | 王五 | 男 | 21 | 医学院 | 4年1班 | 山西 | 太原市 | 小店区兴武小区3栋 |
100404 | 赵六 | 男 | 20 | 英语 | 3年2班 | 江苏 | 徐州市 | 泉山区解放路21号 |
大家可以对比一下表一和二,表二在表一的基础上,将'地址"字段拆分为"省份"、"市(县区)"、"详细地址"。如果《学生信息表》的按地区查询操作比较频繁,那么表二在很大程度上提高了用户对学生学籍所在“地区”的操作效率,不用再从“地址”字段中提取“地区”信息,因此表二的设计满足了域原子性设计,也就是满足了第一范式。
2.第二范式2NF(表中除主键外的字段都完全依赖主键)
第二范式是在第一范式基础上建立的。第二范式有两个重点:(1)表中必须有主键;(2)其他非主属性必须完全依赖主键,不能只依赖主键的一部分(主要针对联合主键而言)。
例如:学生体育选修课考试成绩表
学 号 | 课程编号 | 课程 | 代课老师 | 成绩 |
100101 | 101 | 篮球 | 张 一 | 88 |
100202 | 102 | 羽毛球 | 李 二 | 87 |
100303 | 101 | 瑜伽 | 杨 三 | 79 |
100404 | 105 | 足球 | 胡 四 | 70 |
学 号 | 课程编号 | 成绩 |
100101 | 101 | 88 |
100202 | 102 | 87 |
100303 | 101 | 79 |
100404 | 105 | 70 |
表四 选修课信息表
课程编号 | 课程 | 代课老师 |
101 | 篮球 | 张 一 |
102 | 羽毛球 | 李 二 |
101 | 瑜伽 | 杨 三 |
105 | 足球 | 胡 四 |
将表中课程信息单独分离出来,符合了第二范式原则。表三中的非主属性都依赖于主键,即,“成绩”字段完全依赖于“学号”和“课程编号”组成的联合主键,符合第二范式原则。这样设计,在很大程度上减小了数据库的冗余。
3.第三范式3NF(表中除主键外的字段都完全直接依赖,不能是传递依赖)
不能是传递依赖,即不能存在:非主键列 A 依赖于非主键列 B,非主键列 B 依赖于主键的情况。
第二范式(2NF)和第三范式(3NF)的概念很容易混淆,区分它们的关键点在于,2NF:非主键列是否完全依赖于主键,还是依赖于主键的一部分;3NF:非主键列是直接依赖于主键,还是直接依赖于非主键列。
不符合第三范式的例子:
学号, 姓名, 年龄, 所在学院, 学院联系电话,关键字为单一关键字"学号";
存在依赖传递: (学号) → (所在学院) → (学院地点, 学院电话)
存在问题:
数据冗余:有重复值;
解决:分成学生表,学院表即可。
简单来说:
1NF:列表字段不可分;
2NF:有主键且非主键依赖主键;
3NF:非主键字段不能相互依赖;