第一范式,第二范式,第三范式,BCNF范式理解

分类:编程 |

对于数据库的规范化理论总是明白->忘记->学习->明白->忘记->学习

注意: 满足第一范式的可能存在第二范式的问题, 满足第二范式的可能存在第三范式的问题,

另: a. 满足第二范式的一定满足第一范式

     b. 满足第三范式的一定满足第一范式和第二范式


主要原因还是因为自己没有好好用在实践上, 即没有用理论去指导实践

1. 模糊概念:  候选码 与 主码区别, 
    官方定义: 若关系中的某一属性或属性组的值能唯一的标识一个元组。
    个人理解: 比如学号,身份证号, 为候选码, 而学号为主键, 主键可以作为另一个关系的外键

2. 部分依赖传递依赖 理解: 

   官方定义: 
    部分函数依赖设X,Y是关系R的两个属性集合存在X→Y若X’是X的真子集存在X’→Y则称Y部分函数依赖于X。
    举个例子通过AB能得出C通过A也能得出C通过B也能得出C那么说C部分依赖于AB。
    
    完全函数依赖设X,Y是关系R的两个属性集合X’是X的真子集存在X→Y但对每一个X’都有X’!→Y则称Y完全函数依赖于X。
    举个例子通过AB能得出C但是AB单独得不出C那么说C完全依赖于AB.
    
    传递函数依赖设X,Y,Z是关系R中互不相同的属性集合存在X→Y(Y !→X),Y→Z则称Z传递函数依赖于X。
    举个例子通过A得到B通过B得到C但是C得不到BB得不到A那么成C传递依赖于A

个人理解: 


---------------------------------------------------------------------

2019.10.12 补充: 

非规范化的关系模式, 可能存在的问题包括: 数据冗余, 更新异常, 插入异常, 删除异常

image.png


先理解函数依赖的概念:

重要: 部分函数依赖, 针对的一定是组合键  (如果没有组合键, 则不可能存在部分函数依赖)

image.png

再理解键的概念:

image.png

取候选键: 重要的一点是 入度为 0 的一定是候选键的集合中

image.png


实在不清楚可以画个有向图, 这样比较容易理解:

image.png


以上是范式的基础, 有了这个基础, 理解范式就简单多了:

image.png


实例说明范式: 

image.png


image.png


image.png


image.png

---------------------------------------------------------------------



部分函数依赖:  关系类型为m:n的设计方法, 即一个学号对应多门课程:

示例表 (学号学生姓名、年龄、性别、课程、课程学分、系别、学科成绩系办地址、系办电话)下面存在如下的依赖关系。 

把选课关系表SelectCourse改为如下三个表

  • 学生Student(学号姓名, 年龄性别系别系办地址、系办电话)

  • 课程Course(课程名称, 学分)

  • 选课关系SelectCourse(学号, 课程名称, 成绩)。



再如: 

image.png


image.png


传递函数依赖: 关系类型: : m:1

        学生表Student(学号姓名, 年龄性别系别系办地址、系办电话)关键字为单一关键字"学号"因为存在如下决定关系 

       学号→ (姓名, 年龄性别系别系办地址、系办电话) 

        但是还存在下面的决定关系 

       (学号) → (所在学院)→(学院地点, 学院电话) 

        即存在非关键字段"学院地点"、"学院电话"对关键字段"学号"的传递函数依赖。 

        它也会存在数据冗余、更新异常、插入异常和删除异常的情况。 

        根据第三范式把学生关系表分为如下两个表就可以滿足第三范式了 

        学生(学号, 姓名, 年龄, 性别系别) 

        系别(系别, 系办地址、系办电话)。 


image.png


第一范式、第二范式、第三范式
基础知识
实体现实世界中客观存在并可以被区别的事物。比如“一个学生”、“一本书”、“一门课”等等。值得强调的是这里所说的“事物”不仅仅是看得见摸得着的“东西”它也可以是虚拟的比如说“老师与学校的关系”。
属性教科书上解释为“实体所具有的某一特性”由此可见属性一开始是个逻辑概念比如说“性别”是“人”的一个属性。在关系数据库中属性又是个物理概念属性可以看作是“表的一列”。
元组表中的一行就是一个元组。
分量元组的某个属性值。在一个关系数据库中它是一个操作原子即关系数据库在做任何操作的时候属性是“不可分的”。否则就不是关系数据库了。
码表中可以唯一确定一个元组的某个属性或者属性组如果这样的码有不止一个那么大家都叫候选码我们从候选码中挑一个出来做老大它就叫主码。
全码如果一个码包含了所有的属性这个码就是全码。
主属性一个属性只要在任何一个候选码中出现过这个属性就是主属性。
非主属性与上面相反没有在任何候选码中出现过这个属性就是非主属性。
外码一个属性或属性组它不是码但是它别的表的码它就是外码。
第一范式
第一范式列不能再分。
第二范式
第二范式建立在第一范式的基础上非主属性完全依赖于码。 
简单说消除部分依赖。
什么是码 表中可以唯一确定一个元组的某个属性或者属性组如果这样的码有不止一个那么大家都叫候选码我们从候选码中挑一个出来做老大它就叫主码。注意码可以包含多个属性。
要理解第二第三范式需要理解完全函数依赖、部分函数依赖、传递函数依赖。
完全函数依赖
定义设X,Y是关系R的两个属性集合X’是X的真子集存在X→Y但对每一个X’都有X’!→Y则称Y完全函数依赖于X。
比如通过学号->姓名
部分函数依赖
定义设X,Y是关系R的两个属性集合存在X→Y若X’是X的真子集存在X’→Y则称Y部分函数依赖于X。
需要借用知乎刘慰教师的例子用一下自己也理解了很长时间。
码用(学号+课程),为什么要加课程呢因为不同课程成绩是通过学号查不出来的。
不过用(学号+课程)当作码是不是有些问题
(学号+课程)->姓名但是学号->姓名
(学号+课程)->系名但是学号->系名
(学号+课程)->系主任但是学号->系主任
这个就是部分依赖说实话我看定义一脸懵逼。
要是上面那张表符合第二范式。需要将表拆分为两张表。
一张是 学号、课程、分数表
另外一张是 学号、姓名、系名、系主任表
传递函数依赖
设X,Y,Z是关系R中互不相同的属性集合存在X→Y(Y !→X),Y→Z则称Z传递函数依赖于X。
https://blog.csdn.net/rl529014/article/details/48391465
采用这位大佬的例子 
在关系R(学号 ,宿舍, 费用)中(学号)->(宿舍),宿舍=学号(宿舍)->(费用),费用!=宿舍所以符合传递函数的要求
第三范式
满足第二范式的条件下不存在传递函数依赖。
要满足第三范式在分成两张表的时候第二张表还是有问题?
学号->系名系名->系主任 传递依赖。
需要将系名和系主任另外新建一张表。
总结
第一范式简单说 列不能再分
第二范式简单说 建立在第一范式基础上消除部分依赖
第三范式简单说 建立在第二范式基础上消除传递依赖。
码表中可以唯一确定一个元组的某个属性或者属性组如果这样的码有不止一个那么大家都叫候选码我们从候选码中挑一个出来做老大它就叫主码。
主属性一个属性只要在任何一个候选码中出现过这个属性就是主属性。
非主属性与上面相反没有在任何候选码中出现过这个属性就是非主属性。
BCNF范式
https://www.2cto.com/database/201404/290140.html
BCNF是3NF的改进形式
一个满足BCNF的关系模式的条件:
  1.所有非主属性对每一个码都是完全函数依赖。
  2.所有的主属性对每一个不包含它的码,也是完全函数依赖。
  3.没有任何属性完全函数依赖于非码的任何一组属性。
如上表
(仓库名管理员)->(物品名数量)
(管理员物品名)->(仓库名数量)
但是(仓库名)->(管理员) 不满足第二条
所以需要改成两种表
第一张仓库名管理员
第二张仓库名物品名数量

--------------------- 

参考了

https://www.zhihu.com/question/24696366 

https://www.cnblogs.com/lca1826/p/6601395.html

https://blog.csdn.net/u013164931/article/details/79692402 



传递函数依赖: 同时存在两个主键, 即如下, 学生证号和借书证号, 而且学生证号用确定学生证名称, 借书证号用于确定借书证名称, 

这样的设计就存在问题: 


学生证名称学生证号学生证办理时间借书证名称借书证号借书证办理时间

解决方法拆表:

关系1: 学生证号   学生证名称    学生证办理时间,借书证号
关系2: 借书证号   借书证名称    借书证办理时间

此关系类型是: 1:1