10.数据库设计入门:从学生视角看三大范式与软性约定
目录
一、数据库设计:了解为主,少数记背
二、范式:软性约定,不是硬性规定
三、三大范式:简单了解,实践中体会
1. 第一范式(1NF):列必须是“原子数据”
2. 第二范式(2NF):消灭“部分函数依赖”
3. 第三范式(3NF):消灭“传递依赖”
四、总结
一、数据库设计:了解为主,少数记背
“数据库设计以了解为主,不需要死记硬背,少数关键地方要记住”。后面开发写多了表、写多了代码,自然能找到更优解——别一开始就死磕理论,实践出真知~
二、范式:软性约定,不是硬性规定
范式是设计数据库表的基本规范和约定,就像写代码的“最佳实践”“指导方针”。
它和
create table语法不同:create table是硬性的语法规定(必须严格遵守);范式是软性的约定(日常开发遵守到第三范式即可,其他高阶范式一般不用考虑)。
三、三大范式:简单了解,实践中体会
日常开发常见场景,遵守到第三范式就够用了。下面逐个拆解,结合课堂截图理解:
1. 第一范式(1NF):列必须是“原子数据”
第一范式的核心是:数据表的每一列都是不可分割的原子数据项,不能是集合、数组、对象这类“非原子数据”。
MySQL 本身没有数组/对象这样的类型,所以建表时要注意列的“原子性”。举两个反例:
反例1:
class表设计成(classId, name, studentId),其中studentId用逗号分隔(比如1,2,3,4)。这违反了第一范式——因为studentId列可以拆分成多个独立的学生ID,不是“原子”的。反例2:学生表的“学校”列,直接存“学校名+学校地址+学校电话”(比如“XX大学+XX路XX号+123456”)。这也能继续拆分,所以也违反第一范式。
2. 第二范式(2NF):消灭“部分函数依赖”
第二范式的前提是满足第一范式,然后要求:不存在非关键字段对任意候选键的“部分函数依赖”。
先明确几个概念:
候选键:可以理解成主键(一条记录的身份标识),可以是单个列,也可以是多列组合(联合主键)。
非关键字段:不属于候选键的列。
部分函数依赖:不必通过完整的候选键,就能确定一个记录(比如只靠学号,就能确定学生姓名)。
完全函数依赖:必须通过完整的候选键,才能确定一个记录(比如成绩需要“学号+课程名”一起确定)。
来看一个“学生课程成绩表”例子:
这个表的候选键是“学号 + 课程名”(因为只有这两个组合能唯一确定一条记录)。但存在很多问题:
学生姓名、年龄、性别:只依赖“学号”(部分依赖,不用看课程名就知道是谁);
学分:只依赖“课程名”(部分依赖,不用看学号就知道是哪门课的学分);
成绩:依赖“学号+课程名”(完全依赖,必须两者结合才知道成绩)。
这种“部分依赖”会导致数据冗余(比如李四的姓名和年龄,每次选不同课程都要存一次,重复了)和维护灾难(比如改李四的年龄,要改所有他选课的行,漏改就会歧义)。
所以第二范式的约束是:消灭部分依赖——通常做法是拆分表(比如把学生信息单独放“学生表”,课程信息放“课程表”,成绩放“分数表”)。
3. 第三范式(3NF):消灭“传递依赖”
第三范式的前提是满足第二范式,然后要求:不存在非关键字段对候选键的“传递依赖”。
简单说,就是“非关键字段不能依赖另一个非关键字段”。比如:如果 A→B,B→C,那么 A→C 就是传递依赖(A是候选键,B、C是非关键字段,C依赖B,B依赖A,所以C传递依赖A)。
比如上表:
1.只要 id 确定了,学号,姓名,年龄,性别,还有学院信息都明确了~~
那就是直接的依赖~~
2.但是关于学院电话和学院地址对于Id来说其实是传递依赖,
学院确定了,学院电话和学院地址就确定了~~
同学确定了,学院就确定了
这其实是--不科学的设计~~
四、总结
本篇博客记住几个点:
范式是软性约定,不是语法硬规,日常到第三范式足够;
第一范式抓“原子性”(列不可拆);
第二范式抓“完全依赖”(消灭部分依赖,避免冗余和维护问题);
第三范式抓“传递依赖”(进一步精简);
实践出真知,写多了表自然能找到更优解~
