本文共 1718 字,大约阅读时间需要 5 分钟。
设计数据库的时候,所需要遵从的一些规范的集合叫做范式。
设计时,需要按顺序遵从这些要求,且是一个一个地遵从。
这些范式一共有六个,当然六个范式并不需要全部实现,依照业务需求,满足对应的范式即可,但是每一个范式都会涵盖之前的烦事,所以满足一个范式还要把它之前的范式,按照其排列顺序去满足。如果你的业务需求需要到第三范式,需按照顺序先满足第一,第二范式,再满足第三范式。
越高的范式数据就的冗余越小(数据重复出现的次数越小)
在实际开发中,第三范式基本可以满足绝大部分的需求
请记住,第二范式并不是教你如何设计数据表,而是对你设计完的数据表进行检查,所以在设计的时候只需按照业务需求即可,而范式是让开发者对自己设计数据库进行检查而已。
请注意,在互联网上看到关于范式的例子可能看上去很奇怪,这是因为这些例子其实是为了讲述三种范式硬攒在一起的,正常开发中,你只要脑子正常,都不会设计出这样脑残的表。
第一范式
每一个列必须是单一列,而不能是复合列
明显地,数据库根本就不支持复合列,所以当我们遇到这种情况的时候就要拆分成单个列。结果如下:
符合第一范式后仍然存在较多问题:
仅仅符合1NF的设计,仍然会存在数据冗余过大,插入异常,删除异常,修改异常的问题,例如下面:
每一名学生的学号、姓名、系名、系主任这些数据重复多次。每个系与对应的系主任的数据也重复多次——数据冗余过大
假如学校新建了一个系,但是暂时还没有招收任何学生(比如3月份就新建了,但要等到8月份才招生),那么是无法将系名与系主任的数据单独地添加到数据表中去的 (注1)——插入异常
假如将某个系中所有学生相关的记录都删除,那么所有系与系主任的数据也就随之消失了(一个系所有学生都没有了,并不表示这个系就没有了)。——删除异常
假如李小明转系到法律系,那么为了保证数据库中数据的一致性,需要修改三条记录中系与系主任的数据。——修改异常。
第二范式的作用就是避免这些问题。
第二范式
第二范式看上去有些复杂,但是其实道理很简单:
第二范式是指每个表必须有主关键字,其他列与主关键字,主键组,都具有依赖关系。
所谓依赖,有些类似于数学中的函数,我们都知道很多函数,X值是自变量,Y值是因变量,一个X值唯一对应一个Y值,而反过来,一个Y值就不一定只对应一个X值,这当中,Y就是依赖X的。换到数据库这个语境下,主键其实就是数学函数中的自变量X。而依赖于主键的列就是Y,所以,第二范式指的就是:一个表中的其他列都要依赖于这个表的主键,或者主键组。
主键组:不过数据表和数学函数不同的是,数据表可能会出现多个列做自变量的情况,比如学号和课名加起来才能确定分数,如果其他列对这个两个合成的主键组都能产生依赖关系,那么也算满足第二范式,这个设计也是合理的。
所以利用第二范式自查,可以发现上图的表明显是不符合的,在上图中,姓名、系名、系主任、都是依赖于学号,而学科和分数并不依赖于学号,所以这个表设计是不合理的,解决方法就是:将符合第二范式的列合并进一个表中,将不符合的列重新建表,直到每一个表都符合第二范式的要求。重新设计的表如下。
上表为成绩表,下表为学生表,这样就满足了第二范式。不要认为学号和系名系主任不是依赖关系,一个学号相当于一个学生,一个学生当然只有一个系,一个学生自然也只有一个系主任。
第二范式最终想要达成的效果就是,消除表中所有与主键无关的数据,确保剩下的字段都要和主键有关。
成绩表现在没什么问题,但是学生表出现问题了,系名和老师都要依靠学号才能出现,如果学生被删除,系名和系主任就没了,这样设计还是有缺陷,这时候就需要第三范式了。
第三范式
第三范式是在第二范式的基础上进一步进行限制,要求其他列只能依赖主键/主键组,而不允许其他列彼此之间存在依赖关系。
成绩表中问题就是存在,系主任虽然直接依赖学号,但是系主任还依赖着系名的情况,第三范式不允许出现其他列除了依赖主键的同时又依赖其他列的情况,所以还是要拆表,结果如下:
至此,三种范式介绍完毕,为了更容易理解,我并没有采用范式定义的原话的用词,比如属性,码,属性组等,看懂了也就自然能够对号入座。
转载地址:http://lkppi.baihongyu.com/