数据库—设计规范(依赖、范式、分解)
函数依赖
- 如果在一个二维表中:Students(Sno , name, age),Sno 是这个表中的主键,所以对于其他属性来说,Sno决定name,Sno决定age,反过来则叫做name函数依赖于Sno…
- 定义:主码决定其他属性,其他属性函数依赖于主码
- 非平凡函数依赖
SC(Sno,Cno,Grade)这么一个表中解释,首先主码是Sno和Cno联合主键,然后Grade必须要联合主键才能唯一标识,否则就是非平凡的。(一般研究的都是非平凡函数依赖) - 平凡函数依赖
假如:SC(Sno,Cno,Grade,Cname)中讨论Cname的函数依赖,则Cname只需要Cno就能唯一标识,对于联合主键来说只是用了一部分,那么这个叫做部分函数依赖,同时这种依赖叫做平凡函数依赖。(因为这每一个联合主键表都会有,所以平凡)- 总结的说法就是:在对于联合主键这里就一定会出现的情况(平凡函数依赖),只有一个主键的不会有,所以只要出现了联合主键就必然有平凡函数依赖。但这里只是引出一个定义,后面只会研究非主属性,而不会对于主属性还研究是否依赖自己
认识了平凡和非平凡依赖后开始进入正题
- 完全函数依赖
SC(Sno,Cno,Grade,Cname)中,Grade就是完全函数依赖于联合主键,而不是依赖其中一个 - 部分函数依赖
对于非主属性部分依赖于主键的也就是出现了联合主键,非主属性仅仅依赖于某个而已的时候就叫做部分函数依赖。 - 完全函数依赖有什么用? 部分依赖有什么问题?
个人理解:举一个极端情况,假如说出现一个表有联合主键,有一个非主属性仅仅依赖于联合主键(主属性)中的一个的时候就出现了一个问题就是你的联合主键标识就显得冗余了,对于这个非主属性来说你的联合主键没啥用,只要一个就可以标识了,到时候查询的时候你的另一个也感觉是用不太到。 - 主码与候选码
主码只能设置一个(可一个属性也可联合属性),当出现非主属性函数依赖的时候就可以考虑是否是联合主码出问题了是否能将其多余的修改成一个主属性作为主码,还是说要单拎出来分解出来一个新表。- 另外在候选码中,他自己本身也能够唯一标识一个元组,但假如说没有选他做主属性的时候还能继续完善,就是最完美的要到达主属性除了自身外还要完全依赖于其他候选码,注意是候选码而不是其他主属性,而是其他所有的候选码,不管是否被选中为主属性(BC范式的要求)
范式
第一范式
关系数据库最基本的要求。
- 满足每一个属性都是不可再分(小的斗胆认为自己不会写出这么沙壁的东西)
- 存在的问题
- 函数依赖
因为你仅仅是满足了不可再分,很可能很多漏洞还存留着。
- 函数依赖
第二范式
- 首先是满足第一范式
- 然后第二范式必然是为了解决第一范式存在的问题,那就是解决部分函数依赖。
- 满足非主属性完全函数依赖于主码(主属性)
- 存在的问题
- 存在传递依赖函数,即可能出现:一个主码决定a非主属性,然而a这个非主属性又决定b这个非主属性就叫做传递函数依赖。(primarykey->a->b)
- 即:非主属性出现了传递函数依赖关系
到底怎么解决的
主要是通过分解来解决的,将原本第一范式的进行分解后到达了第二范式。
第三范式
- 首先第三范式有点特殊,他是要满足第一范式的,书上没有说明要满足第二范式,但是我认为只要能细分到属于第三范式即可,无须说我满足了某某范式这一说。(因为我看到网上好多的答案都不同一,有的说二三范式其实隶属于一个范式只是二范式是特殊的三范式等等)
- 三范式解决的必然是二范式中传递依赖的
- 三范式必然要满足完全函数依赖
- 三范式中的属性不可再分(无可厚非的必须要满足第一范式)
- 即三范式:所有的非主属性定要完全函数依赖于主属性,且非主属性也不存在传递依赖关系
到底如何解决的
主要是通过分解来解决的,将原本第二范式的传递依赖进行分解后到达了第三范式。
- 第三范式还存在着某些数据库的插入与删除异常(其实到这里一般的小项目就OK了)
- 问题存在主要是第三范式只解决了非主属性的问题,主属性的问题还没解决。
BC范式(BCNF)
- 首先要满足第一(第三范式基本的也要满足,但是书上也没说,和第三范式没写满足第二范式一样,网上答案也不统一说法)
- 解决插入删除异常
- 满足第一范式后,写出的所有的依赖关系,都必须是属于候选码(只要是候选码就行,没有说明是非得主码)
- 这里比第三范式说的更明白了,就是一个关系中列出的所有函数依赖,左边的那个决定性的属性都必须是属于候选码(只要是候选码就行,没有说明是非得主码)
- 这里我刚接触的时候愣了很久才搞明白,就是用我们学平凡依赖非平凡依赖的时候,列出所有的函数依赖,然后这里的BS范式分析的就是这些函数依赖左边的决定性属性(或联合属性)必定是我们在这个关系中的候选码(只要是候选码就行,没有说明是非得主码)
范式学习总结
- 解决方式都是通过分解属性之间的联系
- 我个人不太喜欢范式说法,为何要定义这么一说要满足几几范式,何必呢,无非是用来衡量数据库好坏的一个方式,其实我觉得只要设计出来的数据库合理,给程序用查询的速度高效,满足用户与程序员即可。
如何分解低范式->高范式
-
分解后必须保持原有的函数依赖
- 原因很简单,假如说是用户提的需求固然不能修改他给的函数依赖(人家说这个程序一定要鸡再有蛋或者先有蛋再有鸡那就不能把人家的需求改掉)
-
分解后具有无损连接
- 意思是你未分解前的数据元组,在你分解后(假如说分解了两个表),那么这些表进行自然连接后所得的数据必须和你的原有的(原本未分解前给的数据一模一样),这样才叫做无损连接(必须是一模一样,少了几条不行,多了也不行,别看名字叫无损连接,数据多了也是错)
-
如何分解:这里就是具体问题具体分析了,一般来说正常思维都不会分解得离谱到哪里去,只要按照规范化去整,尽可能分解拆分到力所能及的最高范式即可
-
(因为有时候不是不能完美,而是这个东西他本身就不能太完美。)
本文来自博客园,作者:竹等寒,转载请注明原文链接。