数据库三大范式详解:概念、应用与优化

发表时间: 2024-06-13 13:48

一、前言

我们一个小伙伴是今年6月份毕业,今天在和他沟通最近面试的情况,面试官主要问他什么的问题,他说面试官看他是24届的学生,主要问他了学校学习的技术比如操作系统、数据库结构,数据库原理等知识,在数据库原理这里面试官问到了数据库的范式,针对这个问题,小伙伴没有回答的很清楚,所以我就准备写一篇文章来复习一下数据库的范式

二、数据库的设计

设计关系数据库时,遵从不同的规范要求,设计出合理的关系型数据库,这些不同的规范要求被称为不同的范式,各种范式呈递次规范,越高的范式数据库冗余越小。但是有些时候一昧的追求范式减少冗余,反而会降低数据读写的效率,这个时候就要反范式,利用空间来换时间。

三、数据库范式的分类

1、第一范式(1NF)

第一范式(1NF)是数据库设计的基础准则。它的核心要求是,一个符合第一范式的关系模式R应确保其所有字段均由不可分割的最小数据单元组成,即字段中的数据必须为原子值。换句话说,R中的每一列都只包含不可再分的信息,确保了数据的原子性。

2、第二范式(2NF)

第二范式(2NF)是在第一范式的基础上,对数据库表的设计提出了更严格的要求。它要求表中的每个非主属性必须完全函数依赖于整个主键。换句话说,如果一个表采用复合主键,那么该表中的所有非主属性都必须依赖于这个复合主键的所有组成部分,而不仅仅是其中的某一部分。这样的设计避免了部分依赖,确保了数据的一致性和完整性。

3、第三范式(3NF)

第三范式要求非主属性之间没有传递依赖。简单来说,非主属性不应该依赖于其他非主属性。这有助于消除冗余和更新异常。

四、案例讲解

1、第一范式【确保每一列都保持原子性】

  1. 顾名思义,就是要求每一列都是原子,不可再分;什么叫列可再分,或者不可再分呢?
  2. 比如以学生举例
SELECT * FROM student;+----------------------+--------+-------+| student |     course | score |+----------------------+--------+-------+| 竹子,男,185cm | 语文 | 95 || 竹子,男,185cm | 数学 | 100 || 竹子,男,185cm | 英语 | 88 || 熊猫,女,170cm | 语文 | 99 || 熊猫,女,170cm | 数学 | 90 || 熊猫,女,170cm | 英语 | 95 |+----------------------+--------+-------+
  1. 在上述的学生表中,其中有一个student学生列,这一列存储的数据则明显不符合第一范式:原子性的规定,因为这一列的数据还可以再拆分为姓名、性别、身高三项数据,因此为了符合第一范式,应该将表结构更改为:
 +--------------+-------------+----------------+--------+-------+| name | sex | height | course | score |+--------------+-------------+----------------+--------+-------+| 竹子 | 男 |   185cm  | 语文 		| 95 || 竹子 | 男 |  185cm 	| 数学 		| 100 || 竹子 | 男 |  185cm 	| 英语 		| 88 || 熊猫 | 女 |  170cm 	| 语文 		| 99 || 熊猫 | 女 | 1 70cm 	| 数学 		| 90 || 熊猫 | 女 |  170cm 	| 英语 		| 95 |+--------------+-------------+----------------+--------+-------+

2、第二范式【保证每一列都是和主键有关的】

  1. 第二范式是在第一范式的基础上提出的,所以满足第二范式就一定满足第一范式,也就是说要想符合第二范式必须先满足第一范式。(第一范式是第二范式的必要条件,反过来第二范式是第一范式的充分条件)
  2. 第二范式的要求表中的所有列,其数据都必须依赖于主键,也就是一张表只存储同一类型的数据,不能有任何一列数据与主键没有关 系,还是上面的那张表数据为例:


  1. 我们先分析一下表结构。

(1)假设学号是表中的唯一主键,那由学号就可以确定姓名和年龄了,但是却不能确定课程名称和成绩。

(2)假设课程名称是表中的唯一主键,那由课程名称就可以确定学分了,但是却不能确定姓名、年龄和成绩。

(3)虽然通过学号和课程名称的联合主键,可以确定除联合主键外的所有的非主键值,但是基于上述两个假设,也不符合第二范式的要求。

(4)那我们应该如何调整表结构,让它能复合第二范式的要求呢?

  1. 修改后的表

3、第三范式【确保每个列都是直接依赖主键,而不存在间接依赖】

  1. 在满足第二范式的情况下,消除传递依赖。在任一主键都可以确定所有非主键字段值的情况下,不能存在某非主键字段 A 可以获取 某非主键字段 B


  1. 为了满足第三范式,我们需要确保表中的所有数据元素都是不可分割的基本数据项,并且不包含其他数据项的信息。换句话说,表中的每个字段都应该直接与主键相关,而不是依赖于其他字段。
  2. 在上面提供的例子中,存在一个函数依赖关系:学号能确定姓名、班级和班主任;班级能确定班主任。这里的班主任依赖于班级,而班级又依赖于学号。为了符合第三范式,我们需要消除这种间接依赖。
  3. 学生表


  1. 班级表

  1. 通过把班级与班主任的映射关系另外做成一张映射表,我们就成功地消除了表中的传递依赖了。

五、总结

  1. 第一范式(1NF):它要求表中的每一列数据都必须是不可分割的基本数据项。这意味着表中的每个字段都应该是一个原子的值,不包含任何列表或结构化的数据。
  2. 第二范式(2NF):在第一范式的基础上,它要求每张表都只描述一种业务属性,即一张表应该只关注一件事情。这通过确保表中的所有非主键字段都完全依赖于主键来实现,从而避免了数据冗余和更新异常。
  3. 第三范式(3NF):进一步构建在第二范式之上,它要求表中除主键外的每个字段都应该是独立的,不依赖于其他非主键字段。这样,每个字段都直接与主键相关联,而不是通过其他字段来推导。
  4. 这三个范式共同构成了数据库设计的基础,有助于创建出结构清晰、逻辑性强、易于维护和查询的数据库表。通过遵循这些范式,我们可以确保数据的完整性和一致性,避免不必要的数据冗余,并提高数据模型的灵活性。