3.6 范式
正如前面所提,Dr. Codd首先描述了数据规范化。他在1971年和1972年发表了几篇论文来描述前三种范式。后来Codd和其他人定义了额外的范式。
3.6.1 第一范式
第一范式(1NF)的目标是去除实体中的重复分组和非原子数据。数据符合1NF时,实体的每个属性都是离散的(换句话说,都是原子的)。术语atomic由atom演变而来,是指可以独自存在的、不可分割的最小粒子。
第一范式去除实体中的重复分组和非原子数据。
当且仅当数据表的所有列只包含原子值时,即满足第一范式。
要想使数据模型符合1NF,必须将重复的分组分裂成单个实体以消除分组。换句话说,在单个实体中不要使用多个属性来存储相似的数据。表3-2的示例数据显示了某大学的STUDENT信息系统。
该数据多处违反了1NF。首先,课程在STUDENT中确实是重复的,因此,课程信息应转移到独立的实体。此外,要为所有的实体都指定标识符。标识符是实体的主码。
谨慎地为各实体选择合适的主码。这可能比较棘手,最先想到的可能是选择CourseNum作为COURSE实体的主码。但就该数据的情况来看,还需要更多的信息来识别课程信息。课程完成日期可用于STUDENT和COURSE的组合,即除非有学生参加并修完了该课程,这门课程才算完成。
第二个违背1NF的地方是,属性StudentName中包含了非原子数据。学生的姓名可以分解为:名、中间名和姓。由于可以分割,因此违背了第一范式。1NF的最终结果见表3-3和表3-4。
3.6.2 第二范式
第二范式(2NF)确保每个实体的所有属性都依赖主码。将1NF转换成2NF,要为那些适用于多条记录的属性创建单独的实体,并为该新实体分配外码使之与原来的实体相关。简单来说,实体实例不应依赖除实体主码以外的任何东西。
第二范式确保每个实体的所有属性都是依赖的。
当且仅当满足第一范式,并且每一个非主属性都完全依赖主码时,即满足第二范式。
再来看一下表3-3和表3-4,实体COURSE中有些课程是重复的,如“英语经典I”和“人的上升”,这就违背了2NF。要解决这个问题,需要找出那些不依赖码的属性,将它们删除。这些被删除的属性,连同它们依赖的主码一起放到一个新的实体ENROLLMENT中。原来实体的主码则保留在原实体中。
规范化的另一个好处是,你会经常需要为新创建的实体指定新的属性。例如,也许新的实体COURSE要为每门课程分配若干学分计算到毕业学分中。因此,创建一个新的属性来存储每个特定课程的学分。当然,也可以决定STUDENT同样需要更多信息,如地址、电话号码和出生日期,但为了简单起见,暂时将它们省略了。
2NF规范化的最终结果如表3-3(实体STUDENT没有改变)、表3-5和表3-6所示。
3.6.3 第三范式
第三范式(3NF)确保实体的属性间不存在关联,该实体内的每一个属性都只依赖主码。对于满足第三范式的数据模型有种半开玩笑的说法:每个属性都依赖码,唯一的码,除了码就没有别的了,噢,Codd!救救我吧!
第三范式确保实体的属性间不存在关联。
当且仅当满足第二范式且每一个非主属性既不依赖码也不传递依赖码时,即满足第三范式。
一种检测是否违背3NF的经验法则是:查看所有的属性值是否适用于不止一个实体实例。如果有这样的属性,将它们转移到单独的实体。
下面再次看看STUDENT实体的信息,是否有违背3NF的情况。仔细研究表3-3中的STUDENT数据,发现有的学生选了同样的主修课,因此,有些主修课的信息是重复的。特别是,在举例中竟然有两名学生都选了英语文学。要解决这个问题,需要将传递依赖码的主修课这一属性删除,并为它创建一个新的实体。表3-7和表3-8显示了更正后的数据,满足3NF。
3.6.4 一个规范化的数据模型
为了做到完美,应为刚才创建的STUDENT数据制作一张满足3NF数据模型的图表。请注意,我们并没有填写关联的可选择性。基于示例中的数据可以做到这一点,但在回答“每名学生都有主修课吗?”这个问题之前还有很多问题需要考虑。当前的数据显示确实如此,但实际上,大多数新生甚至高年级学生可能都没有参加正式的主修课。
3.6.5 进一步的范式
规范化并没有停留在3NF上,其他的范式已经得到大家的认可并记录了。但通常不会有超过3NF的情况。以下是一些其他的范式。
通常不会有超过3NF的情况。
BC范式(BCNF)是修正的3NF。事实上,在Codd后来的著作中就将BCNF称作3NF。当且仅当每一个决定因素都是候选码,即满足BCNF。大多数满足3NF的实体都满足BCNF。
第四范式(4NF)指出如果“一对多”的属性彼此独立,就没有任何实体可以有超过一个“一对多”的关联。当且仅当满足3NF且没有多个多值依赖时,即满足4NF。
第五范式(5NF)指出实体的每一个连接依赖必须是其候选码的结果。
决定因素可以是任何属性值,它能够决定实体实例中其他属性值。