数据库范式

前言

 之前遇到了别人设计的数据库,一个字段里存储的数据带有集合性质,数据之间用逗号区分,刚开始觉得没什么,操作的时候转换一下就好了,后面发现,做删除的时候就傻眼了。左思右想,觉得这样设计肯定是有问题的,于是翻阅了下数据库的书籍,才恍然拾起遗忘的数据库范式。为什么设计范式,必然是有其道理的,不遵循范式,不说必然,很大程度上,会重蹈软件行业前辈们遇过的坑。
 PS:百度百科上都说,傻瓜都不会违反第一范式,我居然还遇到了……

第一范式

 所谓第一范式(1NF)是指在关系模型中,对域添加的一个规范要求,所有的域都应该是原子性的,即数据库表的每一列都是不可分割的原子数据项,而不能是集合,数组,记录等非原子数据项。即实体中的某个属性有多个值时,必须拆分为不同的属性。在符合第一范式(1NF)表中的每个域值只能是实体的一个属性或一个属性的一部分。简而言之,第一范式就是无重复的域。

 用人话讲就是,字段中属性只能是一个,不能有集合性质。不然的话,在修改和删除操作中,直接让你崩溃。
 补充:此外字段中属性也是不开拆分的,不一定说集合才是不可拆分,最好的例子就是地址,如果地址包含省、市、区、详细地址,则是可拆分的。

 如果“地址”:”河南省开封市昭阳区balabla”,这样的话是不满足第一范式的。

 下表这样处理就是满足第一范式的。
满足第一范式

第二范式

 首先满足第一范式
 第二范式(2NF)要求数据库表中的每个实例或记录必须可以被唯一地区分。选取一个能区分每个实体的属性或属性组,作为实体的唯一标识。

如果关系模式R是第一范式的,而且关系中每一个非主属性不部分依赖于主键,称R是第二范式的。

 用人话讲第二范式:任意一个字段都只依赖表中的同一个字段 。
偷下懒,引用下别人的例子,这里引用两个例子,帮助理解。

例子1

满足第一范式的前提下,消除部分函数依赖。

StudyNoNameSexEmailPhoneClassNoClassAddress
01johnMalekkkk@ee.net222456200401A楼2
01maryfamalekkk@fff.net123455200402A楼3

这个表完全满足于第一范式,
主键由StudyNo和ClassNo组成,这样才能定位到指定行
但是,ClassAddress部分依赖于关键字(ClassNo-〉ClassAddress),
所以要变为两个表

表一

StudyNoNameSexEmailPhoneClassNo
01johnMalekkkk@ee.net222456200401
01maryfamalekkk@fff.net123455200402

表二

ClassNoClassAddress
200401A楼2
200402A楼3

例子2

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

改成2张表如下

学生证表学生证学生证号学生证办理时间

借书证表

借书证借书证号借书证把你拉时间

第三范式

  在1NF基础上,任何非主属性不依赖于其它非主属性[在2NF基础上消除传递依赖]第三范式(3NF)是第二范式(2NF)的一个子集,即满足第三范式(3NF)必须满足第二范式(2NF)。简而言之,第三范式(3NF)要求一个关系中不包含已在其它关系已包含的非主关键字信息。

例如,存在一个部门信息表,其中每个部门有部门编号(dept_id)、部门名称、部门简介等信息。那么在员工信息表中列出部门编号后就不能再将部门名称、部门简介等与部门有关的信息再加入员工信息表中。如果不存在部门信息表,则根据第三范式(3NF)也应该构建它,否则就会有大量的数据冗余。简而言之,第三范式就是属性不依赖于其它非主属性,也就是在满足2NF的基础上,任何非主属性不得传递依赖于主属性。

 第三范式是为了消除传递依赖,
传递依赖:设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X。

例子

不存在非主属性对码的传递性依赖以及部分性依赖

StudyNoNameSexEmailbounsLevelbouns
20040901johnMalekkkk@ee.net优秀$1000
20040902maryfamalekkk@fff.net$600

这个完全满足了第二范式,但是bounsLevel和bouns存在传递依赖
更改为:

StudyNoNameSexEmailbouunsNo
20040901johnMalekkkk@ee.net1
20040902maryfamalekkk@fff.net2
bounsNobounsLevelbouns
1优秀$1000
2$600

这里我比较喜欢用bounsNo作为主键,
基于两个原因
1)不要用字符作为主键。可能有人说:如果我的等级一开始就用数值就代替呢?
2)但是如果等级名称更改了,不叫 1,2 ,3或优、良,这样就可以方便更改,所以我一般优先使用与业务无关的字段作为关键字。

列子2

例:如S1(SNO,SNAME,DNO,DNAME,LOCATION)
 各属性分别代表学号, 姓名,所在系,系名称,系地址。
 关键字SNO决定各个属性。由于是单个关键字,没有部分依赖的问题,肯定是2NF。但这关系肯定有大量的冗余,有关学生所在的几个属性DNO,DNAME,LOCATION将重复存储,插入,删除和修改时也将产生类似以上例的情况。
原因:
 关系中存在传递依赖造成的。
 即SNO -> DNO。
 而DNO -> SNO却不存在,
 DNO -> LOCATION,
 因此关键辽 SNO 对 LOCATION 函数决定是通过传递依赖 SNO -> LOCATION 实现的。也就是说,SNO不直接决定非主属性LOCATION。
解决目地:
 每个关系模式中不能留有传递依赖。
解决方法:
 分为两个关系 S(SNO,SNAME,DNO),D(DNO,DNAME,LOCATION)
注意:关系S中不能没有外关键字DNO。否则两个关系之间失去联系。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值