最近更新的频率很快,到今天(2016-6-29)为止,一共有1433名观众,非常感谢大家能有耐心听我的课。
我曾经希望我的课程能破1500人,看来指日可待。
课程地址:http://www.hellobi.com/course/54
此外,希望大家听完课以后去https://www.surveymonkey.com/r/CYQLCTD 填写一下调查问卷,我也好有的放矢,对于我教的不好的地方做调整和改善。
大家好, 这节课我们接着讲讲数据库的规范化. 上节课我们把最常用的第一范式,第二范式,第三范式都讲完了,这节课讲一些更偏理论性的东西,BCNF,第四范式以及第五范式。这部分虽然用起来不很多,但其实也有一些值得借鉴的理念。
好,让我们先来看BCNF。
因为BCNF比第三范式更严格,而又有第四范式的存在,因此它被称为3.5范式。
大家这里需要重点注意的地方是,从BCNF开始,有一些矫枉过正的嫌疑,因此大家要非常注意,要更尊重实际的需求而不是范式本身的正确。数据建模逐步优化追求的绝对不仅仅是减少数据冗余,属性与属性之间的关系尽可能用实体关系表述,而不是通过数据来表述也是非常重要的部分。
我们来先看看维基百科给的定义:
先看第一句话:如果对于关系模式R中存在的任意一个非平凡函数依赖X->A,都满足X是R的一个超键,那么关系模式R就属于BCNF。
这个是什么意思呢?R就相当于一个表,X就相当于R的主键,A就相当于R的一个非主键属性。然后…不行了,我编不下去了,您尝试理解一下吧。开个玩笑,这种东西不举例子实在很难理解.
再看下一段话:BCNF与第三范式的不同之处在于:第三范式中不允许非主属性被另一个非主属性决定,但第三范式允许主属性被非主属性决定;而在BCNF中,任何属性(包括非主属性和主属性)都不能被非主属性所决定。
品味一下,这段话我是理解了,但按这个套路我真讲不明白。
我们还是举个例子吧。
我们先看需求:
每个班级,对应的课程均需要指派一个老师
每个老师只教一种课
那么我们来看这个例子,上面这张表,两个字段做联合主键,班级+课程。根据班级和课程,可以唯一确定教师。这里班级 + 课程是可以唯一确定教师的,并且除了教师再没有其他的非主键属性。因此,显然这张表是复合第三范式的。但我们发现一个问题,就是每个教师只能教一种课,也就是说课程是依赖教师的。在第三范式里是这么定义的,非主键属性只能依赖主键属性,不能依赖于其他非主键属性,但没说主键属性不能依赖于其他非主属性。而BCNF的定义呢,是所有属性都不能依赖于非主键属性。例子里,主键中的一个属性依赖于一个非主键属性,也就是课程依赖于教师。因此这个不符合BCNF。并且,这里我们看一下,我标绿的,是存在冗余的,DAVID+操作系统出现了两次,是吧?
所以,如果按照常规的转换方式呢,应该是下面这个结构一样,把教师和课程移出去单独建表,但这个显然有问题,因为丢了班级,课程和教师的关系。
然后我们来看看怎么办,这里我们发现,实际上在上面这张表里,班级+教师也可以成为主键,是吧?那么,我们把教师和课程调换一下,让班级+教师作为联合主键,然后这个就不符合第二范式了是不是,因为课程只依赖于教师,而不依赖于整个联合主键,然后再建一张表,教师作为主键,课程作为非主属性依赖于教师。然后,变换之后的模型就符合BCNF了。有点复杂是吧?还好这种场景不是很多。
我们这里需要注意一下,就是什么场景下会存在符合第三范式,但不符合BCNF呢?
有俩最基本的条件:
联合主键
还得存在一个可替换的重叠的候选键, candidate key。看上面的例子,班级+教师, 班级+课程都是候选键,其中班级就是两个候选键重叠的主属性.
这里说一点题外话,我做了一下问卷调查,有同学提建议说你这总讲基础知识没意思啊,我这个也是为了考虑更为广泛的同学,比如如果某些新接触数据库的同学,不知道候选键是什么,我这里提重叠的候选键,他就没法理解,所以为了照顾更广泛的同学,我还是得讲一些基础知识。此外,还有同学说我这课题目是高质量,还数据仓库建模,到现在为止,这俩讲的都不多,别着急,后面就有了。
BCNF其实还是挺有用的, 其实我们建模的时候经常不自觉就用到BCNF了. 建模这种工作, 当你熟练了以后, 对于范式这种就会融会贯通, 自然而然建的就是规范化的表, 可以说,规范化建模的过程本身就是你厘清需求的过程。让我们再来看看4NF,第四范式。这里需要提醒大家注意一下,其实从BCNF开始,都非常注重的是数据和数据之间在现实生活中意义的表达,虽然还是在消除冗余,但厘清数据之间的关系,用实体和关系来表述各个属性之间的关系,而不是用数据的内容来表达各个属性的关系,这个意义其实比去冗余更重大。这里我们先介绍一个概念,多值依赖。这个概念的意思我老早就明白,但为了讲今天的课,我四处翻啊,真是难为我,无论中文英文的,就没有一个说人话的,我就是抄出来,大家也很难听懂。我这里直接用我自己的大白话来表述吧。首先得有一个大前提,必须是三个属性作为联合主键。(这里我没特别举例子,其实三个属性以上也是同样的套路,在这我还是用三个属性作为联合主键为例)。大家发现没,BCNF以后都不怎么研究非主键属性了,净研究主键,而且还非得是联合主键。书归正传哈,说,三个属性,在一起做联合主键,假设分别是ABC。从真实的含义上,AB和AC都存在关系,但BC没直接关系,也就是说B的改动不会影响C,C的改动也不会影响B。这种情形,我们称为多值依赖。而第四范式要做的,就是要消除多值依赖。
让我们来看个例子,这张表,三个字段做联合主键,学号,课程,语言,显然符合第三范式。这里我标绿的,就是数据冗余的部分。大家可以看到,学号和课程是有逻辑上的关系的,学生会去选课。学号和语言也有关系,表示学生所具备的语言能力。但课程和语言没关系,也就是说,你改学生的课程不会影响他的语言,反之亦然。那么这个就是多值依赖了,说起来我们总说4NF如何如何只在学术里面讨论,其实也不尽然,这种场景我们其实实际工作中也能遇到。那么怎么改呢?很简单,拆成两张表,把有逻辑关系的,学号+课程作为一张表,学号+语言作为另一张表。这样,逻辑更为清楚了,同时,数据的冗余也减少了。
这里需要特别注意一点,前面讲的多值依赖的概念,AB具有逻辑关系,AC具有逻辑关系,并且BC没有关系,才构成多值依赖,如果BC也有关系,那就不是多值依赖了,这个叫连接依赖。如果AB,AC,BC均存在依赖关系,这个是符合第四范式的,但不符合第五范式,第五范式要做的事就是消除连接依赖。这里我再次强调一遍,从BCNF范式开始,各种花样都是玩在主键上而不是非主键上,并且,更多逻辑上的,语义上的内容添加进来了,你看第四范式和第五范式长的很像,但因为语义上的不同,需要做不同的变换。逻辑,语义上的理解,才是数据库模型规范化设计的精髓,就像我一开始讲的一样,牛吃草,猫吃鱼,奥特曼打小怪物,把分类分对,也就是把恰当的属性放到恰当的实体中,规范化就完成了。不要过于拘泥于,目前的模型是第几范式。
好,我们还是来看一个例子。
看上面的表,三个字段做联合主键,学号,课程和所阅读的书籍。那么结合我刚才介绍的概念,学号和课程逻辑相关,学号和阅读书籍也逻辑相关,同时看数据的内容,阅读的书籍和课程也相关。也就是说,这个没有多值依赖,符合第四范式。但有连接依赖,不符合第五范式,因此做如下变换。这变换很简单了,就是排列组合,C32,从三个里面选俩,变成三张表。说实话,第四范式我们偶尔还能用一下,第五范式好像非常少用,通常上面这张表的设计就可以了,也没多少冗余,设计成下面这样不见得就好。
传说还有第六范式,还有Domain Key神马范式,那些估计都是一些老学究为了标榜自己呆着没事琢磨出来的,茴香豆的茴字有四种写法对我们的实际工作实在没有什么现实意义,所以我也不推荐继续学习下去。而实际上,我们在实际工作中,能到第三范式就可以了,今天的课程只是满足小部分同学对BCNF,4NF这几种范式的好奇心。我觉得对大家或许会有一点点帮助,如果实在弄不明白也不要紧。大家以后自己多做模型, 再回头看这段视频品味就会明白了.
好,今天的课程就到这里,我们下节课再见。
-------------------------------------------
经 okgogogo指正,PPT例子5NF已经修正。稍后更改视频。
特此表示歉意,并对@okgogogo表示感谢!