在数据库设计中,范式是一种重要的概念。通俗的讲,范式就是一种减少数据冗余、避免数据更新异常的设计技术。在本文中,我们将以一个具体的例子来解析范式在数据库设计中的作用。
首先,让我们来看看原始数据。假设有一个学校,这个学校是由多个系组成,每个系又有多个专业,每个专业包含多个班级。学生信息存储在班级中。
| 班级编号 | 班级名称 | 学号 | 姓名 | 性别 | 年龄 | 系名称 | 专业名称 |
| -------- | -------- | ---- | ---- | ---- | ---- | -------- | -------- |
| 001 | 信安1班 | 1 | 张三 | 男 | 20 | 信安系 | 信安专业 |
| 001 | 信安1班 | 2 | 李四 | 女 | 19 | 信安系 | 信安专业 |
| 001 | 信安1班 | 3 | 王五 | 男 | 18 | 信安系 | 信安专业 |
| 002 | 计科2班 | 4 | 赵六 | 男 | 20 | 计科系 | 计科专业 |
| 002 | 计科2班 | 5 | 钱七 | 女 | 19 | 计科系 | 计科专业 |
从上表可以看出,该表存在以下问题:
1. 数据冗余:同一班级中的学生信息重复出现。
2. 数据更新异常:如果某一个学生所在的班级发生变化,那么需要修改多行数据。
接下来,我们通过引入范式来解决这些问题。
第一范式(1NF)
第一范式要求关系表中的每个属性都是原子性的,即不可再分。我们可以通过将班级信息和学生信息分开来解决数据冗余的问题,将班级编号、班级名称、系名称、专业名称存储在班级表中,将学生编号、班级编号、学生姓名、性别、年龄存储在学生表中。
班级表:
| 班级编号 | 班级名称 | 系名称 | 专业名称 |
| -------- | -------- | ------ | -------- |
| 001 | 信安1班 | 信安系 | 信安专业 |
| 002 | 计科2班 | 计科系 | 计科专业 |
学生表:
| 学号 | 班级编号 | 姓名 | 性别 | 年龄 |
| ---- | -------- | ---- | ---- | ---- |
| 1 | 001 | 张三 | 男 | 20 |
| 2 | 001 | 李四 | 女 | 19 |
| 3 | 001 | 王五 | 男 | 18 |
| 4 | 002 | 赵六 | 男 | 20 |
| 5 | 002 | 钱七 | 女 | 19 |
第二范式(2NF)
第二范式要求每个非主属性都完全依赖于关系的主键,即不存在部分依赖。在学生表中,学生的姓名、性别、年龄完全依赖于学生的学号,班级编号只是部分依赖于学号,因此需要将班级信息作为新的表存储。将班级编号、系名称、专业名称存储在班级表中,将学号、班级编号存储在学生表中。
班级表:
| 班级编号 | 系名称 | 专业名称 |
| -------- | ------ | -------- |
| 001 | 信安系 | 信安专业 |
| 002 | 计科系 | 计科专业 |
学生表:
| 学号 | 班级编号 |
| ---- | -------- |
| 1 | 001 |
| 2 | 001 |
| 3 | 001 |
| 4 | 002 |
| 5 | 002 |
第三范式(3NF)
第三范式要求不存在传递依赖。在学生表中,班级信息的系名称和专业名称存在传递依赖于班级编号,因此需要将系信息的表和专业信息的表存储。将系编号、系名称存储在系表中,将专业编号、专业名称、系编号存储在专业表中。
班级表:
| 班级编号 | 专业编号 |
| -------- | -------- |
| 001 | 001 |
| 002 | 002 |
专业表:
| 专业编号 | 专业名称 | 系编号 |
| -------- | -------- | ------ |
| 001 | 信安专业 | 001 |
| 002 | 计科专业 | 002 |
系表:
| 系编号 | 系名称 |
| ------ | ------ |
| 001 | 信安系 |
| 002 | 计科系 |
通过引入范式,我们可以解决数据冗余和数据更新异常等问题。同时,使用第三范式将数据拆分成多个表,便于数据管理和维护。