在前面学习了数据库的多表查询语言后,有没有考虑过这些数据库是怎么设计的呢?
既然做笛卡尔积的多表连接那么费时间,为什么不直接全部都作为一个表来查询呢?
总而言之,我们来判断什么是好的数据库关系模式?并自己也能设计出来!
先回答一个问题,为什么不直接全部都作为一个表来查询呢?
答案是会造成 数据冗余,更新异常,数据不一致啦~
所以解决了上面三个点,就是一个好的数据库关系模式
前面讲关系模式的概念时,提到描述关系模式的五元组中的F,代表的就是属性间数据的依赖关系的集合
数据依赖(Data Dependency)
即R(U,D,Dom,F)可简化为R(U,F)
- R:关系名
- U:组成该关系的属性集合
- D:属性组U中属性所来自的域
- Dom:属性向域的映像的集合
- F:属性间数据的依赖关系的集合
数据依赖可分为
- 函数依赖(Functional Dependency ,FD)
- 范式的概念
- 1NF,2NF,3NF,BCNF
- 多值依赖(Multivalued Dependency,MVD)
- 连接依赖(Join Dependency,JD)
函数依赖
-
定义:
类似数学的函数,Y=F(X) Y依赖于X或者X决定Y,则称X→Y。 若Y不依赖于X或者X不决定Y,则称X!→Y。【这个数学符号嘛,打不出😂简单理解:在箭头上打一斜杠】
- 平凡函数依赖和非平凡函数依赖
- 平凡函数依赖
X→Y,Y∈X
如:(学生学号,学生姓名)→学生姓名 - 非平凡函数依赖
X→Y,Y!∈X
(学生姓名,所在系)→学生学号
- 非平凡函数依赖
- 平凡函数依赖
- 完全函数依赖和部分函数依赖
- 完全函数依赖
(学生学号,课程编号) f→成绩 【注意符号: f在箭头上面】
成绩完全依赖于学生学号和课程编号 - 部分函数依赖
(学生学号,课程编号) p→所在系【注意符号: p在箭头上面】
所在系只依赖于学生学号 - 传递函数依赖
由学生学号 f→所在系 和所在系 f→系主任
则学生学号 t→系主任【 t在箭头上面】
- 传递函数依赖
- 部分函数依赖
- 完全函数依赖
超码、候选键和主属性和主码的区别:【在数据库,键=码,即意思相同】
- 如二维表 (学生学号,课程编号,学生姓名,所在系,系主任,成绩)
- 其中主属性为:学生学号,课程编号。其他为非属性
- 若选择学生为主码,则课程编号为候选键
- 反之亦然。
- 候选键和主属性都可以唯一标识一个元组
- 超码是主属性
数据冗余,更新异常,数据不一致的根源!!!
- 数据冗余:表信息数据重复出现,没有良好的关系模式
- 更新异常:部分依赖导致
- 数据不一致:传递依赖导致
范式(Normal Form)
-
定义
数据依赖满足一定约束的关系模式
-
第一范式(1NF)r(R)∈1NF
判断标准:关系模式r(R)的每个属性对应的域值都是不可再分的。 如快递地址存在歧义,也要细分为省、市、区
-
第二范式(2NF)
判断标准:所有的非主属性都完全函数依赖于r(R)的候选码,不允许依赖于部分的候 选码 方法:把原有表拆分为多个表,直到满足判断标准 作用:消除部分依赖引起的数据冗余和更新异常问题
-
第三范式(3NF)
判断标准:所有的非主属性不能存在传递依赖 方法:把原有表拆分为多个表,直到满足判断标准 作用:消除传递依赖引起的数据不一致问题 有个bug:允许存在主属性对候选码的传递依赖和部份依赖
-
BC范式(BCNF)Boyce-Codd
判断标准: 所有非主属性都完全依赖于每个候选码 所有主属性都完全函数依赖于每个不包含它的候选码 没有任何属性完全函数依赖于非候选码的任何一组属性