第三范式之上

说到范式,常常碰到的一个说法就是,数据库设计知足第三范式就能够了,足够了。这个说法有时给人一种暗示,知足更高的范式是件复杂的事情,或至少是件繁琐的事情,不必。数据库

但实际上,不少模型一旦知足了第三范式,每每也已经知足了更高的范式。一些以第三范式为标准设计的库,极可能也已知足第四甚至第五范式,尽管它称呼起来都是说知足了第三范式。数据库设计

现实中的业务每每有着自身的规律与约束,一个库模型,在知足第三范式时也知足了更高的范式,有时是一个很天然的事。相反,知足了第三范式但违反了更高的范式,这时候就要当心对待,这里很容易发生设计错误。学习

在实际的操做中,高范式每每表明着更多的链接,有时为了更好的响应速度、更便捷的某些操做,设计时会特地下降范式或违反范式。这种设计理念与本文的重点----“知足了第三范式但违反了更高的范式,这时候很容易发生设计错误”要注意区分开。spa

 

在继续下文前,先回顾下前三个范式的概念:设计

第一范式,表的列(关系的属性)是不可再分的,不能是复合的,每一列各自表示一个属性。这个也是关系数据库最基本的要求,不知足第一范式也就没法说什么关系的数据库。
第二范式,在第一范式的基础上,表中的每一行能够被惟一地区分。
第三范式,知足第二范式,并在候选键上不存在传递依赖。代理

 

“一个设计知足了第三范式,但可能违反了更高范式”--这条警示何时该响起?如下诸状况就是一些高危区:1.一个表是否与多个表关联,特别是参与了多个多对多关系。2表包含着复合键。3使用的不是天然键而是代理键。blog

 

下面以一些容易出错的关系表举例:

1.知足第三范式,但不知足第四范式
数学

第四范式关注的是多值依赖。io

1.1 学生关系表基础

学生关系表(学生,社团,课程)

显然,学生能够参加多个社团,也须要学习多个课程,这个表中社团属性依赖于学生,课程属性也依赖于学生,而后这2个属性有多种组合数据,这违反了第四范式。
现实中社团与课程的组合意义不大,容易判断。

以下面关系表的记录。注意这里为方便描述给的是模拟记录,实际中三个字段存的更多是id值而且是三个表的外键。

 

1.2 快递送货表

快速送货表(快递员,订单,商品)

这里快递员按照订单进行派送,将订单上的全部商品送到顾客手上。
这种类型的模型也包含着多值依赖,而且这种模型一个高危的地方在于,每安排一个订单,可能须要插入多条数据,如某订单中包含3件商品,就必须插入三条数据。这里的更新容易形成数据不当。

 该模型能够分解为2个关系表:

关系表1
(快递员,订单)

关系表2
(订单,商品)

 

2. 知足第三范式,但违反第五范式
第五范式要求候选键能推导出全部链接依赖。

2.1 教学日程计划表

教学日程计划表(教室 ,教师 ,课程)

在这个模型中,教师有教学任务,课程安排在具体的教室进行。即便老师们个个都是全能,什么课都能教,课程安排也要与教室类型匹配,生物课拿着待解剖的青蛙跑到钢琴教室显然不合适,现实中的老师也各有所长,虽然数学语文老师常来教体育课,但你应该不但愿你的数学语文是体育老师教的。调侃的话很少说,这个模型里有2个依赖:1.课程依赖教室的类型。2.教师依赖具体的课程。

以下教学日程计划表模拟数据:

 

 

模型涉及的表以下:

教师表(TeacherID,Name)
教室表(RoomID,RoomName)
课目表(CourseID,CourseName)
教师任教表(TeacherID,CourseID)
教室科目表(RoomID,CourseID)
日程计划表(TeacherID,CourseID,RoomID,StartTime,EndTime)

模型:



如上图,日程计划表中的三个外键TeacherID,CourseID,RoomID组成联合主键,并分别关联三个实体表Teacher,Course,Room。这种状况没法避免如上面(教学日程计划表)模拟数据最后一条记录,室内篮球馆原本应该上体育课,但安排了生物实验课,任课老师也发生错误安排了数学老师。

为防止异常数据,模型能够调整为:

 

上图并无改变表,只是改变了表之间的关系。最主要的变化是日程计划表Schedule的外键关联指向的是2张关系表TeacherCourse,RoomCourse。图中发现Schedule的三个外键仍然和原来的同样,若是对此有疑惑,不妨设想在关系表TeacherCourse,RoomCourse上各自设立代理主键key1,key2,此时Schedule的联合主键就是(key1,key2)。不过在这个模型中,代理主键会屏蔽掉不少关键信息,链接时也无必要,所以使用3个键做联合主键,但注意此时的键关系与原模型是不一样的。


无损分解是一种分析是否违反较高范式的方法。当你有个大表,能够把其中的某些字段分离出来做为单独的表,通过去重DISTINCT后作驱动表与原来的表进行左外链接 LEFT OUTER JOIN,若是获得的结果没有任何数据丢失,则原来的表可能违反了一些范式,须要检查是否存在异常数据。当进行这样的分析时,表中应该有足够的数据,少许的数据不必定能知足判断。



总结:1.大多数数据模型已经知足了高范式,明显违反高范式时须要注意。2.多对多关系、复合键、代理键是容易出现违反高范式的地方。3.无损分解是一种有效的检测方法。4.第六范式是将表的关系减小到只存在一个非关键属性,这样会致使表数量膨胀,但能够避免空值列。第六范式的状况不多,未在文中讨论,放在这里只是记录一下。

相关文章
相关标签/搜索