数据库三大范式 | 青训营笔记

178 阅读3分钟

这是我参与「第三届青训营 -后端场」笔记创作活动的第4篇笔记

在关系型数据库的设计中,为了建立冗余的数据较小,结构合理的数据库,必须遵守一定的规则,而这种规则就被称为范式。

范式是符合某一种级别的关系模式的集合,目前关系型数据库有六种范式,分别为:

for(int i = 1; i <= 6; i++){
    System.out.println("第" + ChineseUtils.toChineseNumber(i) + "范式 (" + i + "NF)");
}

由于不想用这六种范式水字数,所以用了一个代码来表示,然后那个Utils是用来把数字转换成中文的。

虽然有六种范式,但是平时设计数据库的时候,只需要满足三范式就行了,甚至第三范式也不用严格执行,不过这不是本篇文章的重点,本篇文章重点是介绍一下数据库设计的三大范式。

第一范式(1NF)

第一范式用来确保每列的原子性,要求每列(或者每个属性值)都是不可再分的最小数据单元。

例如:学生选课表(学号,课程号,学生姓名,学生性别,学生生日,学生年龄,学生专业号,学生专业名称,课程信息,课程成绩)

在这个表中,课程信息这一列可以拆分成课程名称,课程学分,不是原子性的列,所以可以改成:学生选课表(学号,课程号,学生姓名,学生性别,学生生日,学生年龄,学生专业号,学生专业名称,课程名称,课程学分,课程成绩)

第一范式实现起来非常简单,只要确保每列都只存储一种不可再分的数据即可。

小吐槽:第一范式的反例我想了好久,这个也太难想了,真的会有人不遵守第一范式吗?

第二范式(2NF)

第二范式在第一范式的基础上更进一层,要求表中的每列都和主键相关,即要求实体的唯一性。如果一个表满足第一范式,并且除了主键以外的其他列全部都依赖于该主键,那么该表满足第二范式。

在第一范式的例子中,主键是(学号,课程号)。而显然,学生姓名,学生性别,学生生日,学生年龄,学生专业号,学生专业名称只依赖于学号。而课程名称,课程学分只依赖于课程号。

所以可以将这个表进行如下拆分:

学生(学号,姓名,性别,生日,年龄,专业号,专业名称)

课程(课程号,名称,学分)

选课(学号,课程号,成绩)

这样的数据库就满足第二范式了。

话说这些的我都快不认识课程这俩字了。

第三范式(3NF)

第三范式(3NF)在第二范式的基础上更进一层,第三范式是确保每列都和主键列直接相关,而不是间接相关,即限制列的冗余性。如果一个关系满足第二范式,并且除了主键以外的其他列都依赖于主键列,列和列之间不存在相互依赖关系,则满足第三范式。

从第二范式的例子中,我们可以看到,学生表中,年龄可以根据生日计算得出,且专业名称依赖于专业号,所以我们可以将学生表拆成这样:

学生(学号,姓名,性别,生日,年龄,专业号)

专业(专业号,专业名称)

这样,这个数据库就是满足第三范式的了。

结语

数据库这三大范式在数据库设计中发挥着至关重要的作用,我们在设计数据库的时候,一定要牢记三大范式,尽量不要违背它们。