
1、BCNF、4NF、5NF—— 白猫黑猫,抓到耗子就是好猫,一切从实际出发,因地制宜。
2、完整性约束——祖国必须统一,也必然统一。


(1)函数依赖
简单说函数依赖就是:某个属性集决定另一个属性集时,称另一属性集依赖于该属性集。比如,比如在设计学生表时,一个学生的学号能决定学生的姓名,也可称姓名属性依赖于学号,对于现实来说,就是如果知道一个学生的学号,就一定能知道学生的姓名,这种情况就是姓名依赖于学号,这就是函数依赖。函数依赖又分为非平凡函数依赖,平凡函数依赖;从性质上还可以分为完全函数依赖、部分函数依赖和传递函数依赖。
◇ 平凡函数依赖:当关系中属性集合Y是属性集合X的子集时(Y⊆X),存在函数依赖X→Y,即一组属性函数决定它的所有子集,这种函数依赖称为平凡函数依赖。
◇ 非平凡函数依赖:当关系中属性集合Y不是属性集合X的子集时,存在函数依赖X→Y,则称这种函数依赖为非平凡函数依赖。

◇ 完全函数依赖:设X,Y是关系R的两个属性集合,X’是X的真子集,存在X→Y,但对每一个X’都有X’!→Y,则称Y完全函数依赖于X。(!→ 表示不能决定)
◇ 部分函数依赖:设X,Y是关系R的两个属性集合,存在X→Y,若X’是X的真子集,存在X’→Y,则称Y部分函数依赖于X。
◇ 传递函数依赖:设X,Y,Z是关系R中互不相同的属性集合,存在X→Y(Y !→X),Y→Z,则称Z传递函数依赖于X。
(2)第二范式(2NF)
第二范式(2NF)是在第一范式(1NF)的基础上建立起来的,即满足第二范式(2NF)必须先满足第一范式(1NF)。第二范式(2NF)的规则是要求数据表里的所有非主属性都要和该数据表的主键有完全依赖关系;如果有哪些非主属性只和主键的一部份有关的话,它就不符合第二范式。例如,下表中学号和课程号作为联合主键,可以决定非主属性(成绩、课程名称、学分),而课程号也可以单独决定部分非主属性(课程名称、学分),即非主属性(课程名称、学分)依赖于主键中的一部分,出现了非主属性对主键的部分依赖。这违反了第二范式的要求。

改变的方法就是将部分依赖从该表中去除,成立一个新表。即拆分成下表所示。


满足第三范式(3NF)必须先满足第二范式(2NF),并且要求一个数据库表中的属性不依赖于其它非主属性。也就是说不能存在非主属性对主键的传递依赖。例如,在下表中,学号是主键,学号决定其他非主属性(姓名、系别、办公室地点),而非主属性系别也决定着办公室地点,这就产生了由学号 → 系别 → 办公地点的非主属性对主键的传递依赖。

解决的方法还是拆,将具有传递依赖的属性从该表中独立出去,如下图所示,

拆分后,将原表的系别作为新表的主键,同时,将其保留在原表中作为外键。这样就消除了非主属性对主键的传递依赖。

BC范式,又称巴斯范式,是由Boyce和Codd提出的,比3NF又进了一步,通常被认为是修正的第三范式。相对于第三范式,BC范式的要求更加严格。第三范式只是要求关系满足第二范式,且非主属性不传递依赖于关系的主键,而BC范式则是对R的每个属性都做要求,即主属性也不能存在对主键的部分依赖和传递依赖。例如,下表中学号和课程是联合主键,身份证号则为候选关键字,是主属性。

由于学号和课程号能决定身份证号,学号本身也能决定身份证号,这就存在了主属性(身份证号)对主键(学号+课程号)的部分依赖。同时,身份证号也可以决定学号,这就存在了主属性(身份证号)对主键(学号+课程号)的传递依赖,即学号+课程号 → 身份证号 → 学号。解决的方案就是将具有部分依赖和传递以来的属性分离出去。如下表所示。


4NF就是限制关系的属性之间不允许有非平凡且非函数依赖的多值依赖。例如,下表中对于课程的每一个值,教师都有一组值与之对应,而无论参考书取何值,这显然是多值依赖。

解决方法,依然是拆分,将表中多值依赖的属性拆分到不同的表中。


第五范式(5NF):是终极范式。如果关系模式R中的每一个连接依赖均由R的候选码所隐含。所隐含是指在连接时,所连接的属性均为候选码,且将表尽可能的切成小块,减少数据冗余。例如,下表中的金额属于导出属性,被称为“计算列”,而单价和数量属于“数据列”,金额属于冗余字段。数据冗余的优点是检索的速度快,以空间换时间。缺点是重复数据较多时,冗余的数据更新较为困难。

在实践中,并不推荐严格恪守设计范式,一直规范化到5NF,当然更不推荐完全不考虑规范化原则,通常规范化到3NF。


关系完整性的用于保证数据库中数据的正确性。系统在进行更新、插入或删除等操作时都要检查数据的完整性,核实其约束条件,即关系模型的完整性规则。在关系模型中有三类完整性约束:实体完整性、域完整性和参照完整性,其中实体完整性和参照完整性约束条件,称为关系的两个不变性。
◇ 实体完整性:指表中行的完整性。主要用于保证操作的数据(记录)非空、唯一且不重复。即实体完整性要求每个关系(表)有且仅有一个主键,每一个主键值必须唯一,而且不允许为“空”(NULL)或重复。比如,学生表中学号不能为空。
◇ 域完整性:也称用户自定义完整性约束,是指数据库表中的列必须满足某种特定的数据类型或约束。其中约束又包括取值范围、精度等规定。比如,性别列可以设置约束,取值范围为[ 男,女 ],而年龄可以设置约束为[ 0, 150 ]。

◇ 参照完整性:要求若属性组F是关系模式R1的主键,同时F也是关系模式R2的外键,则在R2的关系中,F的取值只允许两种可能:空值或等于R1关系中某个主键值。
例如,学生实体和专业实体是1对多的联系,即一个学生只属于一个专业,一个专业有多名学生,在将其转换为关系数据模型时,需要学生建一张表,专业建一张表,并将 1 的关键字专业号放到学生表中作外键。这时,学生表中的专业号外键要么为空,要么匹配专业表中的值。也就是说,当学生表中的专业号为空时,说明,学生刚刚录取,尚未分配专业,匹配专业表中的值,这个好理解。参照完整性约束的含义就是外键需要参照主表中的值,不能与主表的值不同,即某个学生被学校不存在的专业录取。


例题:假设有关系R及其包含的各种依赖,如下图所示,其中AB为联合主键,关系的上方表示关系的主键依赖,下方表示关系R的函数依赖。

分析:从图中可以看出这是一个典型的1NF结构,因为该结构的数据分量是不可分的,即不存在表中有表的情况。但它却不是2NF,因为该结构包含了非主属性对主码的部分依赖(B→C),也就是说C应该依赖于联合主键AB而不应该依赖于联合主键的一部分。
第一步,将每个主键(PK)都写在单独的一行,将初始的PK写在最后一行。

第二步,投影分解,将第一步确定的PK属性的各种依赖放在该PK属性后面。

第三步,投影分解,将第二步确定的函数依赖再进行分解。

