数据库范式理解
数据库范式是什么
数据库范式(Normal Form, NF)指的是设计数据库关系模型时应该要满足的标准规范要求。
为什么要遵守数据库范式
使表结构更合理,避免数据冗余,节省存储空间,便于插入、删除和更新。
但是范式越高意味着表的划分更细,用户不得不把原本相关联的数据分解到多个表中,当需要这些数据时只能采用连接表的方式将数据重新合并在一起,影响查询性能。所以,对于更新频率不高、查询频率高的数据库系统来说,有时会故意保留部分冗余方便数据查询。
数据依赖关系
数据的依赖关系完全决定于数据的语义。
函数依赖(Functional Dependency, FD)是最基本的依赖关系,指的是一个或一组属性的值可以决定其他属性的值。比如,学生学号决定姓名、年龄等属性的值。
多值依赖(Multi-valued Dependency, MVD),指一个或一组属性的值可以决定其他属性的一组值。函数依赖是多值依赖的特例。在实际应用中出现的不多。
传递依赖,假如 A 函数依赖于 B,B 函数依赖于 C,则 A 传递依赖于 C。
1NF
Every attribute of a relation must be atomic.
表里的每一个属性都是不可切割的。
2NF
在 1NF 的基础上,不存在非主属性对主键的部分函数依赖。
假如存在一张学生信息表:S(SID, SNAME, AGE, CID, GRADE),表的主键是学号 SID 和课程号 CID。其中学号和课程号决定分数,但是学生姓名、年龄只通过学号就能决定,因此存在部分函数依赖,也就是姓名、年龄部分函数依赖于学号。
不满足 2NF 的表结构会存在以下问题:
- 插入异常:无法插入尚未选课的学生的个人信息(主键不能为空)
- 删除异常:如果学生退选课程时,学生的个人信息会同时被删除
- 难以更新:表中存在大量的数据冗余,更新的时候很难维护数据的一致性。
解决方法:按照“一事一地”的原则设计表结构,把原表分解成 S(SID, SNAME, AGE) 和 SC(SID, CID, GRADE) 两张表。
One fact in one place
3NF
在 2NF 的基础上,不存在非主属性对主键的传递依赖。
假如存在一张雇员表:EMP(EMPID, SAL_LEVEL, SALARY),其中雇员编号决定薪资级别,薪资级别决定薪资,SALARY 对主键 EMPID 存在传递依赖。所以这张表满足 2NF 但不满足 3NF。
不满足 3NF 的表结构会存在以下问题:
- 插入异常:员工的薪资级别还没定的时候,薪资级别和薪资之间的关系也无法录入
- 删除异常:假如某个薪资级别对应的员工都被删除了,该薪资级别对应的薪资信息也丢失了
- 难以更新:表中存在大量的数据冗余,更新的时候很难维护数据的一致性。
解决方法:按照“一事一地”的原则设计表结构,把原表分解成 EMP(EMPID, SAL_LEVEL) 和 SL(SAL_LEVEL, SALARY) 两张表。