规范化可以使数据库更加适应数据结构的变化,使数据库抵御某些类型的错误。数据库规则从弱到强的次序:第一、二、三范式,Boyce_Codd范式,第四、五范式,域/键范式(DKNF

第一范式:

   列名唯一;

   行列次序无关;(若有次序要求,则加列priority

   每列数据类型唯一;

   两行不同;(相同则加列quantity

   每列单值;(妻子列不能写多个名字)

   列不包含重复的组。(不要建家畜1,家畜2……等重复的列

第二范式:

符合第一范式;

所有的非键值字段均依赖所有的键值字段。

例子:歌手、演出时间、歌手等级、歌手类型

问题:歌手和演出时间构成主键,但等级和类型都不依赖演出时间(属于键值字段)。

异常:

   若更改了某一时段的歌手类型,其他时间段的该歌手类型冲突。

   在增加一个歌手时,必须同时增加演出时间。

   若取消了歌手的某一时间的表演,可能该歌手的全部信息就会丢失。

解决:将等级和类型移到新表中。

第三范式:

   符合第二范式;

   一个非键值字段不依赖于另一个非键值字段。(即不包含传递相关性)

   例子:读者、书名、作者、出版时间

   问题:书名依赖读者,而其他字段又依赖书名。

   异常:

       若修改了一本书的出版时间,而其他行的该书的时间则冲突。

必须在确定读者的情况下才能插入一本新书。

删除一读者可能会丢失一本书的信息。

   解决:将作者、出版时间移到新表中。

Boyce_Codd范式(BCNF):

   符合第三范式;

   每个决定因子都是一个候选建。

   概念:

       超键:包含唯一值的一组字段。(既能够标识表中某个特定的行)

       候选键:最小的超键。(即从候选键中删除任一列,将不再是超键)

       决定因子:决定另一字段取值的字段

   例子:学号、姓、名字、职务(一名学生可有多个职务,一个职务也可有多个学生)

   问题:学号决定了姓和名字,但学号不是一个候选键。(学号+职务才是候选键)

   异常:

       若更改了一员工的姓,其他行该员工的姓则发生冲突。

       不给学生指派职务,则无法添加学生记录。

       删除一职务,可能会删除该学生的记录。

   解决:将姓,名字移到新表中。

第四范式:

   符合BCNF

   不包含无关的多值依赖性。

概念:

无关的多值依赖性:技能依赖员工,工具依赖员工,但技能和工具是独立的。

   例子:员工,技能,工具(一个员工可有n种技能,m种工具)

   问题:技能、工具具有无关的多值依赖性

   异常:

       一名员工的技能修改了,其他工具对应的技能则冲突。

       一名员工丢失了一技能,需删除对应的n行。

       一名员工增加一技能,必须增加对应的n行。

   解决:将技能和工具放在两个表中,分别和员工关联。

第五范式:

   符合第四范式;

   不包含相关的多值依赖性。

   概念:

相关的多值依赖性:汽车品牌依赖修理工,发动机类型依赖修理工,但品牌和发动机类型是相关的。

   例子:修理工,汽车品牌,发动机类型

   问题:品牌和发动机类型具有相关的多值依赖性。

   解决:将品牌和发动机类型放在两个表中,与修理工关联;

         同时还要有个品牌和发动机的关联表。

域/键范式(DKNF):

   除了域约束和键约束外,该表不包含其他约束。

   概念:

       域约束:字段的值满足属于其域内的值。

       键约束:构成一个键的字段中的值是唯一的。

   例子:名字,省份,城市,区,邮编

   问题:省份/城市/邮编存在约束,该约束不是域约束或键约束。

         若将邮编拿出来则是DKNF,但我国的邮编有上千个,且有时还会变化。这样表的规模就很庞大,维护也不方便。所以有时也需要必要的冗余。

   符合DKNF该范式的数据库,可以避免所有的数据异常;但有时满足该范式需要花费很大的代价,使维护很困难。一般较低级别的规范化就能得到足够好的结构,大多数情况不需要采用该范式。


注:本文参考《数据库设计解决方案入门经典》(美)Rod Stephens著 王海涛 宋丽华译 一书