发表于: 2017-12-04 23:49:48
1 813
今天完成的任务:
一、准备小课堂的内容。
范式:Normal Form 范式是“符合某一种级别的关系模式的集合,表示一个关系内部各属性之间的联系的合理化程度”。很晦涩吧?实际上你可以把它粗略地理解为一张数据表的表结构所符合的某种设计标准的级别。就像英语的四级和六级,相对代表了英语的水平的高低。
满足这些规范的数据库是简洁的、结构明晰的,同时,不会发生插入(insert)、删除(delete)和更新(update)操作异常。
数据库范式分为1NF,2NF,3NF,BCNF,4NF,5NF 一般我们在设计数据库结构的时候最多只要满足到BCNF 就可以了。符合高一级的范式必定符合第一级的范式。
详细的说一下1NF,2NF,3NF
1NF的定义为:符合1NF的关系中的每个属性都不可再分。在使用数据库管理系统的时候比如mysql,sqlserver等创建的数据表都满足1NF,如果不满足这个范式,是不能创建成功数据表的。
属性不可再分的意思是每一个字段都是最小的,不包含其他字段。不重复,原子性。
id | 姓名 | 系名 | 系主任 | 课名 | 分数 |
2017001 | 小花 | 搬砖系 | 小花花 | 高数 | 60 |
2017001 | 小花 | 搬砖系 | 小花花 | 英语 | 99 |
2017001 | 小花 | 搬砖系 | 小花花 | 编程 | 99 |
2017002 | 小明 | 英语系 | 小明明 | 高数 | 80 |
2017002 | 小明 | 英语系 | 小明明 | 英语 | 59 |
2017002 | 小明 | 英语系 | 小明明 | 编程 | 99 |
问题:数据冗余,插入异常,删除异常,修改异常的问题。
插入异常:如果需要新建一个系,并且有系主任。但是因为还没有学生开始学习,所以主键是空的,肯定是不能插入的。
删除异常:如果需要把某个系下面学生信息都清空,那么这个系也就不存在了。
修改异常:如果需要把学生的系进行更换,就需要把三条数据里面的系名和系主任都修改才可以。
2NF:在1NF的基础上,消除了非主属性对于码的部分函数依赖。
码:假设K为表中的某个属性,如果在K确定了的情况下,这个表里面其他的属性都可以确定,那么K就叫做候选码,也叫码。在表中比如通过id可以获取到姓名,系名,系主任名,但是不能确定课名和分数。课名可以获取分数。
id -------姓名,系名,系主任
课名-----分数
(id,课名)这个属性组就叫做码。
非主属性: 上面说到的码里面的属性就是主属性,包括id,课名。
不是主属性的就是非主属性,包括姓名,系名,系主任,分数。
部分函数依赖:
函数依赖:函数y=f(x) 代表了给定一个x的值,y的值也是确定的。在数据表中,在属性X确定的情况下,必定能确定Y的值,那就说Y函数依赖与X 写作X---Y。
比如:在表中,给定一个学号,必定能得到唯一的一个姓名。那就说姓名函数依赖于学号。
写作:学号---姓名
在表中的函数依赖还有
学号-----系名
学号-----系主任
(学号,课名)-----成绩
完全函数依赖:在一张表中,若 X → Y,且对于 X 的任何一个真子集(假如属性组 X 包含超过一个属性的话),X ' → Y 不成立,那么我们称 Y 对于 X 完全函数依赖,记作 X F→ Y。
比如(学号,课名)-----成绩
学号和课名都是X的真子集,但是如果只有学号,或者只有课名,是不能得到一个唯一的成绩。满足完全函数依赖的要求,所以Y完全函数依赖于X
部分函数依赖:如果Y函数依赖于X,但是Y不完全函数依赖于X,那就叫做部分函数依赖。
比如 (学号,课名)------姓名。
由学号可以得到唯一的姓名,但是由课名不能得到唯一的姓名。所以称为Y部分函数依赖X。
现在可以讨论2NF ,判断是否符合2NF,就是看数据表中是否存在非主属性对于码的部分函数依赖。若存在,则数据表最高只符合1NF的要求,若不存在,则符合2NF的要求。
步骤:
第一步:找出数据表中所有的码。(id,课名)
第二步:根据第一步所得到的码,找出所有的主属性。id和课名
第三步:数据表中,除去所有的主属性,剩下的就都是非主属性了。
姓名,系名,系主任,分数。
第四步:查看是否存在非主属性对码的部分函数依赖。
对于(学号,课名) → 姓名,有 学号 → 姓名,存在非主属性 姓名 对码(学号,课名)的部分函数依赖。
对于(学号,课名) → 系名,有 学号 → 系名,存在非主属性 系名 对码(学号,课名)的部分函数依赖。
对于(学号,课名) → 系主任,有 学号 → 系主任,存在非主属性 对码(学号,课名)的部分函数依赖。
从上面可以看出,这个表是只满足1NF,不满足2NF
怎么使他满足2NF,方法只有一个,就是将一个表拆分为几个小的表,叫做模式分解。模式分解的方法不是唯一的。只要满足范式就可以。
比如数据表里面的示例。
id | 课名 | 分数 |
2017001 | 高数 | 60 |
2017001 | 英语 | 99 |
2017001 | 编程 | 99 |
2017002 | 高数 | 80 |
2017002 | 英语 | 59 |
2017002 | 编程 | 99 |
id | 姓名 | 系名 | 系主任 |
2017001 | 小花 | 搬砖系 | 小花花 |
2017002 | 小明 | 英语系 | 小明明 |
看一下变成2NF的时候,对1NF的问题有没改进
问题:数据冗余,插入异常,删除异常,修改异常的问题。
数据冗余:减少了冗余。
插入异常:如果需要新建一个系,并且有系主任。但是因为还没有学生开始学习,所以主键是空的,肯定是不能插入的。
删除异常:如果需要把某个系下面学生信息都清空,那么这个系也就不存在了。
修改异常:如果需要把学生的系进行更换,就需要把三条数据里面的系名和系主任都修改才可以。 2NF可以只修改一个字段就可以实现。
3NF在2NF的基础之上,消除了非主属性对于码的传递函数依赖。也就是说, 如果存在非主属性对于码的传递函数依赖,则不符合3NF的要求。
传递函数依赖:
如果Y依赖于X,Z又依赖于Y,那就说Z依赖于X。
比如:系名依赖于学号,系主任依赖于系名,那么系主任传递函数依赖于学号。不满足3NF
解决办法是继续拆分表:
插入异常:如果需要新建一个系,并且有系主任。但是因为还没有学生开始学习,所以主键是空的,肯定是不能插入的。 现在需要新建一个系是不会出问题的。
删除异常:如果需要把某个系下面学生信息都清空,那么这个系也就不存在了。
这时候清空只需要清空第二个表,不会影响其他表。
不会出现异常。
id | 课名 | 分数 |
2017001 | 高数 | 60 |
2017001 | 英语 | 99 |
2017001 | 编程 | 99 |
2017002 | 高数 | 80 |
2017002 | 英语 | 59 |
2017002 | 编程 | 99 |
id | 姓名 | 系名 |
2017001 | 小花 | 搬砖系 |
2017002 | 小明 | 英语系 |
系名 | 系主任 |
搬砖系 | 小花花 |
英语系 | 小明明 |
2NF是表中不存在部分函数依赖。
3NF是表中不存在传递函数依赖。
在数据表的设计中,不一定必须遵守3NF,这只是一种规范的数据表设计模式。并且3NF在实际使用中也不一定是最好的,所以在设计表的时候,
还是应该去舍弃一些数据表的规则,比如可以有一些冗余,从而达到性能比较好,比较符合需求的情况。
明天计划:
明天学习怎么使用公司框架。
遇到问题:
方案里面有几个问题,大佬帮忙了。
收获:
方案过了一遍。数据表做好了。
评论