关系型数据库设计范式
为了建立冗余较小、结构合理的关系数据库,设计关系数据库时必须遵循一定的规则, 即关系数据库的设计范式。
第一范式(First Normal Form, 1NF)#
关系型数据库的第一范式要求:
- 所有字段都是不可分割的
举例来说,客户数据表中包含客户名和地址,地址由城市和街道组成。应用经常需要分别访问城市或街道字段。
数据表customers(name,city, street)是符合第一范式的,而数据表customers(name,address)则不满足第一范式的要求。
定义一个满足第一范式的数据表:
courses(student_id, course_id, school_name, president, credit)
primary key(student_id, course_id)
上表仍然存在四个问题:
-
数据冗余: school_name, president属性重复出现
-
插入异常: 若一个新建school没有开始招生则不能加入数据表中
-
删除异常: 若一学院所有学生均毕业,则该学院信息消失
-
修改异常: 若一学院院长更换,则需修改该学院所有学生的数据;
若一学生转院则需修改其所选所有课程的数据。
第二范式(Second Normal Form, 2NF)#
第二范式是在第一范式的基础上定义的,它要求:
-
表的设计满足第一范式
-
除主键外所有属性完全函数依赖于主键
候选码是函数决定所有非主属性的最小集合,但不排除候选码的真子集决定某些而非全部非主属性的情况.
而2NF禁止候选码的真子集函数决定任何非主属性.
如上文数据表:
courses(student_id, course_id, school_name, president, credit)
primary key(student_id, course_id)
school_name和president属性依赖于student_id
属性,不依赖于course_id
属性。
也就是说school,president属性部分函数依赖于主键,不满足第二范式的要求。
若将上表拆分为两个数据表:
courses(student_id, course_id, credit)
primary key(student_id, course_id)
students(student_id, school_name, president)
primary key(student_id)
拆分后的数据表满足了第二范式的要求。
现在分析一下,第一范式没有解决的四个问题:
-
数据冗余: 减少了school_name和president重复出现的次数
-
插入异常: 未解决
-
删除异常: 未解决
-
修改异常: 解决了学生转院的问题,未解决院长更换的问题
第三范式(Third Normal Form, 3NF)#
第三范式定义在第二范式的基础上:
-
表的设计满足第二范式的要求
-
除非主属性直接依赖于主键
看上文数据表的定义
students(student_id, school_name, president)
primary key(student_id)
存在传递函数依赖student_id
->school_name
->president
,不满足第三范式。
进行进一步拆分:
courses(student_id, course_id, credit)
primary key(student_id, course_id)
students(student_id, school_name)
primary key(student_id)
schools(school_name, president)
primary key
拆分后消除了传递函数依赖。
分析第三范式对上述四个问题处理。
-
数据冗余: 除了主键外所有属性只出现一次
-
删除异常: 允许删除所有学生而保留学院信息
-
插入异常: 允许建立没有学生的学院
-
更新异常: 更换院长,学生转院均只需修改一条记录
第三范式基本上可以解决上述问题。
BCNF#
BC(Boyce-Codd)范式在3NF的基础上进一步消除了传递依赖.
BCNF要求:
-
关系模式符合3NF
-
函数依赖集F中所有函数依赖X->F, 左部X必须包含R的所有候选码.
即所有候选码都直接决定所有非主属性.
BCNF分解算法#
给定关系模式R和其上的函数依赖集F, 将R进行满足BCNF的无损连接分解:
-
置初值p =
-
检查p中的关系模式若均满足BCNF则停止分解, 否则重复执行3.
-
在p中选出不满足BCNF的关系模式S, 其中必有非平凡依赖B->C, 且B不是S的候选码.将S分解为S1= {B,C}和S2 = R - {C}, 用S1,S2代替p中S的位置.
示例:
R = {A, B, C} F = {A->B, B->C}
候选码A, 函数依赖B->C, 因为B不是Candidate Key所以要进行分解:
{B, C} {A, B}
第四范式(Forth Normal Form, 4NF)#
4NF要求:
-
必须满足BCNF
-
非主属性不能存在多值
示例:
phone(user_id, phone, cell)
若某用户有多个phone同时又有多个cell时此表设计显然不合理.
可以采用如下的拆分方案:
phone(user_id, phone, type)
拆分后的数据表满足了4NF.
作者:finley
出处:https://www.cnblogs.com/Finley/p/5462610.html
版权:本作品采用「署名-非商业性使用-相同方式共享 4.0 国际」许可协议进行许可。
【推荐】还在用 ECharts 开发大屏?试试这款永久免费的开源 BI 工具!
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· ASP.NET Core 模型验证消息的本地化新姿势
· 对象命名为何需要避免'-er'和'-or'后缀
· SQL Server如何跟踪自动统计信息更新?
· AI与.NET技术实操系列:使用Catalyst进行自然语言处理
· 分享一个我遇到过的“量子力学”级别的BUG。
· C# 中比较实用的关键字,基础高频面试题!
· .NET 10 Preview 2 增强了 Blazor 和.NET MAUI
· 为什么AI教师难以实现
· 如何让低于1B参数的小型语言模型实现 100% 的准确率
· AI Agent爆火后,MCP协议为什么如此重要!