`

关于多值依赖--范式!

阅读更多
原文
http://book.csdn.net/bookfiles/1168/100116834872.shtml
.6 实体中的多值依赖

在本节中,我们会看看下一个层次的规范化。虽然在考虑了实现规范化上所需投入的时间,以及最终数据库的性能开销后,这个层次的规范化并没有被普遍采用,然而,本节和这之前的部分一样绝对重要。

在前面的部分中,我们处理的是属性的结构以及非键属性和键之间的关系。接下来将要讨论的两个范式处理的仍然是非键属性间的关系,但是,现在我们处理的是关系的基数,以及当基数大于一时可能引发的各种问题。

虽然第三范式通常被认为是正确的数据库设计的巅峰,然而,在逻辑设计中,仍然可能留下了一些严重的问题。说得更具体些,本节的范式要处理的是属性之间的多值关系和依赖情况。为此,我们将首先较详细地研究第四范式,然后简单地介绍第五范式。

4.6.1 第四范式

到目前为止,我们的规范化原则处理的都是实体中列之间的冗余。我们没有解决的问题是:如果实体有组合键,而键中的一列或多列仍然持有冗余数据,则会引发若干问题。实体规范化的第四范式讲的就是这些问题。在简单情况下,朝着第四范式前进要解决的是类似于这样的问题:建立模型,将实际情况下需要多值的属性存储为单一值。要解决的第二类问题更加不易把握,因为它处理的是三元关系,以及如何将其分解为更易处理的、更小的表。

为了便于说明,考虑一个将学生分配到班级的实体,同时,我们想要表示每个班级每个学生的老师。因此,我们将老师和学生放到如图4-26所示的ClassAssignment实体中。

这样做看起来很不错,并且,由于展示ClassAssignment实例需要所有的属性,这可以说是个最优的解决方案。然而,进一步的考虑发现这个实体并不让人满意。如果我们现在想要改变一个班级的老师,将不得不对班级中的所有学生实例进行修改,因为每个ClassAssignment实例都包括了班级和老师。

很明显,这样做不是最好的,因为规范化最主要的一点就是消除冗余信息,尤其是消除修改一条信息需要在若干地方修改这条信息的情况。注意到一个班级有若干学生,一名学生可以在若干个班级中,以及共有若干位老师这个事实,可以找到一个简单的解决方案。(我还将一步步地展示一个讲同样问题的例子,教会你如何在不是立刻就有思路的情况下寻找到解决方案。)

为了实现新的解决方案,我们创建3张表:一张针对班级,其他两张分别体现老师与班级的关系以及学生与班级的关系。如图4-27所示显示了修改后的设计。



图4-27 修改后的班级模型

之所以可以这样变形,关键在于学生和老师之间的关系(至少就班级分配来说)是完全围绕着班级进行的。因此,我们不需要体现Student和Teacher实体之间的关系。通过Class实体进行联结,可以得到有关哪个学生由哪个老师授的信息。

这类变形在很大程度上是第四范式要做的事。我们必须打破这种三元关系,将其变为没有冗余信息的更有用的形式。

实体要满足第四范式,必须满足下列条件。

l 实体必须满足BCNF:该条件保证所有键都被恰当地定义了,并且,实体中所有的值都正确地依赖于实体的键。

l 在一个属性与实体的键之间,多值依赖(MVD)必须不能超过一个:能够存储多值,并且与实体的键相关联的属性不能超过一个,否则会出现重复的数据。另外,我们应该保证,对多值属性的每个值,都不会在单值属性中重复它。

看一些例子会有助于弄清楚以上的想法。让我们先看看违反第四范式主要的3种形式:

l 三元关系;

l 潜伏的多值属性;

l 临时数据或历史值。

从我自己的观点来看,理解第四范式非常关键。要遵守第四范式的方法也相当简单。认为第三范式之后的范式没有意义的观点中,存在着一些重大的误解。一旦你明白了在第四范式的级别上规范化的意义,你就再也不会忽略第四范式所代表的内容。

1. 三元关系

在第1章我们简单地看过三元关系。通常,在真实环境下,关系不会表现为简单的二元类型,三元甚至三元以上的关系都很常见。只要我们在键中的任何地方看到了3个(或更多)识别性的或强制的非识别性关系,我们就有可能碰到麻烦(同时,要考虑到三元关系也许是挑选的键不够好造成的)。

考虑我们设计出一套实体来支持会议安排的情况,我们存储了有关会议、发言人以及举行会议所在的房间的信息。

让我们假设需要遵循如下的业务规则集合:

l 一场演讲可以安排多位发言人;

l 一场演讲可以安排在多个房间。

图4-28建模的关系是“发言人—在房间中—的会议上—发言”。


图4-28 “发言人—在房间中—的会议上—发言”关系

这些实体每一个都是BCNF实体。然而,3个实体间的关系很麻烦,因为键包含了3列,尤其是所有的属性都是从其他实体迁移而来。当然,这样做也可能一点错都没有,但是,任何时候发生了类似于这样的情况时,都需要进行一些调查,确保在我们的数据中没有多值依赖,因为它们最终可能会造成问题。

考虑每个会议都同时开展的情况。此时表中需要会议的时间,而这会使情况更为复杂。在这个时候,我们处理的是所有的会议都用一个会议时间的情况。让我们看一组示例数据(我们将房间、发言人和会议联结了起来,这样就能看到自然键)。



第一行没有问题,因为我们这一行是针对会议101,有一个发言人Davidson,在房间River Room中。接下来两行问题开始变得明显起来,因为会议202在一个房间中有两个不同的发言人。这迫使我们在“Room”属性中不必要地重复数据,因为我们现在已经存储了两条会议202是在Stream Room中的信息。如果会议改地方,我们就必须在两处都变更信息,如果我们忘记了这一点,基于目前没显示出来的某个值更新房间信息(比如,通过使用人工键),那我们最终就会得到如下的值。

在这个例子中,我们有重复的“Session”和“Room”属性数据,并且“404”会议有重复的“Session”和“Presenter”数据。当添加或修改数据时,这种数据复制造成的真正的问题就来了。如果我们想要更新Davidson和Hazel在Stream Room中进行发言的“Session”号,则需要修改两行。同样地,如果“Room”分配发生了变化,也有好几行必须修改。

当用这种方式实现实体时,也许不会像这里看到的那样,所有的行的所有列都填满了。接下来,我们会介绍一系列未填满的行,从功能上讲,它们与前面的实体集是等价的。


在这个例子中,有的房间值为null,有的发言人值也为null。我们消除了重复的数据,但现在我们有一些看起来怪里怪气的数据,到处都是null。不仅如此,我们现在不能用null来清楚地表达“我们还不知道会议的发言人是谁”的情况了。我们确实存储了与前面的例子等价的数据集,但是,这些数据的格式让人很难操作。姑且不论这样做是对是错,你也许可以立刻看出这样的数据操作起来是多么地让人烦恼。

为开发一个该问题的解决方案,让我们首先将Presenter作为主要的实体,如图4-29所示。

图4-29 Presenter是主要的实体

然后我们将RoomSessionPresenter实体分解为3个实体,如图4-30所示。

图4-30 以发言人为中心重新组织数据

这显然不是个正确的解决方案,因为除非被分配一个发言人,否则我们永远都不可能决定会议在哪个房间中举行。并且,Davidson在River Room和Stream Room中都有会议,但没有什么内容能够链接回去,告诉我们房间中举行的会议是什么。当我们分解关系时,如果我们丢失了数据的意义,这种分解就被称为有损分解。这里的情况就是有损分解,因此它并不是问题的合理解决方案。

接下来我们尝试着以会议举行的房间为中心,如图4-31所示。

图4-31 现在Room是主要的实体

将数据分解入实体中,如图4-32所示。

图4-32 以Room为中心重新组织数据

这也是个有损分解,例如,我们不能决定到底是谁在202会议上发言。它在Stream Room房间中,并且Davidson、Hazel和Hawkins都要在Stream Room中发言,但是,他们并不都在202会议上发言。所以,再一次,我们要考虑其他的设计。这一次,我们的设计以要举行的会议为中心,如图4-33所示。

看看图4-34中的数据。

最终,我们找对了该问题的解决方案。从这个数据出发,我们可以准确地决定谁在哪个房间、在哪个会议上发言,并且,添加或删除发言人,或甚至是修改房间都没有问题。拿404会议举例。对于404会议,在如下的结果集中,实体SessionRoom和SessionPresenter包含的数据是:


图4-33 现在Session是主要的实体

图4-34 以会议为中心重新组织数据


要向名单中加入一个名叫Evans的发言人,我们只需简单地加入另一行:


现在,这是个恰当的分解,不会有在先前的实体中所碰到的问题。我们现在有与发言人分开的会议集,在外键值中也不再需要null,因为如果我们想要表示一个房间没有被选中开会,我们就不创建SessionRoom实例。如果我们没有选中一名发言人也同样如此。更重要的是,现在我们为一个会议设定多个房间也不会有什么混乱。

如果需要用其他数据来扩展SessionPresenter这个概念,例如,指定一个备选发言人(或者是第一发言人和第二发言人),现在就有一个明确而合乎逻辑的地方来存储这些信息了。请注意,如果我们曾经试图在原来的实体中存储这些信息,那就会违反BCNF,因为AlternatePresenter属性只会与Session和Presenter有关系,与Room无关。

这个过程的关键是寻找属性之间的关系。对这个例子来说,会议和谁在会议上发言之间有关系,会议和会议的举行地点也有关系。反过来说,发言人与会议在哪里举行之间却没有直接的联系。

2. 潜伏的多值属性

我之所以使用“潜伏的”这个词,是因为粗看起来,在本节讨论的属性并不总会出问题。问题在于,某个属性在很多情况下看起来似乎需要的都仅仅是单值,但是,当仔细琢磨这个问题时,会发现其也有需要多值的时候。为了展示这层意思,让我们看看如图4-35的设计模型。

当我们考虑Contact实体时,问题浮出了水面。我们有3个属性:联系人的名字(假设这个名字满足第一范式)、电话号码和地址。名字没什么问题,因为所有的联系人都有一个用来代表他们自己的名字,问题在于,在这个时代,许多人都有不止一个地址和电话号码。所以我们就有了多值属性,需要进一步规范化来解决这个问题。为了允许多值的地址和电话号码,我们可以像图4-36那样修改设计。
[img]
http://dl.iteye.com/upload/picture/pic/64071/b4ed6d4e-b800-33be-bbaa-fa20d3a3aa4e.jpg[/img]
图4-35 包含了潜伏的多值属性的设计

图4-36 模型现在支持多值的地址和电话号码

虽然有多值的电话号码并没有违反第一范式(因为它们都是不同类型的电话号码,而不是同一类型的多个值),然而,它确实给我们带来了更多问题。因为我们只是简单地在属性名上添加了属性的类型(例如,HomeAddressId、FaxPhoneId),所以,如果用户有两个传真号或两个手机号,我们将面临更严重的多值属性问题。不仅如此,当属性的值不存在时,对每个属性我们都需要多个可以为null的值,这种情况当然很不理想,因为从技术上来说,null表示值未知,而不是值不存在。

这样表示关系真是一团糟。例如,如果客户需要对一位联系人增加其配偶的办公室电话号码属性,我们就必须修改模型,而这非常可能需要重写应用程序的代码。

让我们进一步修改设计,将Contact与ContactInformation实体分开,如图4-37所示。

Type属性表明我们存储在实例中的联系人信息的类型,如此一来,我们就可以将某个ContactInformation实例冠以“家庭”(Home)的“类型”(Type),为其附上地址和电话号码。通过这种方式,用户需要多少电话号码和地址,我们就可以加上多少。然而,由于地址和电话号码保存在同一张表中,如果联系人家庭地址和电话号码的数量不同,我们就还是需要在某些值中填入null。

图4-37 分开Contact和ContactInformation实体

在这个阶段,我们需要决定自己想要如何进行下去。我们可能想要一个电话号码与地址关联起来(例如,将家庭电话号码与家庭地址相关联)。就这个例子而言,我们将把ContactInformation实体分解为ContactAddress和ContactPhone(虽然这并不是该问题唯一可能的解决方案),如图4-38所示。

图4-38 用ContactAddress和ContactPhone实体来体现联系人的信息

这个修改消除了残留的多值依赖,因为现在我们可以有许多彼此独立的地址和电话号码,并且,我们可以想定义多少类型就定义多少类型,不需要修改实体的结构。然而,我们还可以再进一步:在逻辑模型中将电话号码和地址建模为不同的实体,再针对Type列加入域实体。这样做之后,我们就可以防止当用户想输入的是“Home”时,却输入 “Some”、“Homer”、“Hume”这样的值。将电话号码和地址建模为不同的实体,还使得我们能够建立用户可配置的约束,这样就可以不修改模型就加入新的类型。我们将在域实体上加入Description属性,它使我们可以说明一个类型的真实用途。Description属性使得我们可以处理如下情况:对一个组织来说,“离开”这种地址类型的意义可能很明白,但对于第一次使用系统的用户来说,其意义却很费解。针对这个类型,我们可以加入说明信息,比如“联系人出差延期,仍然在商务旅行中时的地址”。图4-39显示了我们最终的模型。

图4-39 最终模型

注意,我把添加的Address和PhoneNumber属性设置为替代键,为的是避免每次需要在系统中使用它们时都得设置一个重复的地址。通过这种方式,当我们有5个联系人有相同的办公室地址时,我们就只用修改一个值。在最终的实现中,这也许是所期望的东西,也许不是,因为它会增加复杂性;从商业的角度来看,增加这种复杂性也许值得,也许不值得。

事实上,在检查第一范式、第二范式、第三范式或Boyce-Codd范式时,你往往会发现很多这类问题。例如,回头想想讲第一范式时的Payment1、Payment2等,如果这个字段仅仅是Payment,它看起来会那么扎眼吗?也许不会。如果你在搜索实体时非常严格,并且意识到了支付是某种独立于客户的东西,那么你才有可能做对,否则就很容易忽略它。

范式的定义图



分享到:
评论
1 楼 heming_way 2012-03-31  
谢谢,对我很有用,解答了我对多值依赖的疑问

相关推荐

    数据库范式5nf-第四范式(4NF)数据库管理系统.pdf

    尽管第⼆,第三和Boyce-Codd范式具有功能依赖性,但4NF却具有更为通⽤的依赖性类型,即多值依赖性。 A table or relation is in 4NF if and only if, for each attribute of its non-trivial multivalued ...

    数据库范式5nf-第五范式(5NF)数据库管理系统.pdf

    它旨在通过以多种格式分隔语义连接的关系来存储多值事实,以最⼤程度地减少关系 数据库中的冗余。 A relation R R is in 5NF 5NF if and only if every non-trivial join dependency in R R is implied by the ...

    第3章 关系模式设计理论 3.6 多值依赖和第4范式.flv

    数据库系统原理

     消除XML亚强多值依赖引起冗余的一种分解方法

    提出了弱键路径和XML亚强多值依赖弱范式的定义,通过实例分析XML亚强多值依赖引起数据冗余的原因,提出分解不完全XML文档满足XML亚强多值依赖弱范式的定理。研究成果可较好的处理不完全XML文档中存在XML亚强多值依赖...

    数据库入门(一)范式理解:1NF,2NF,3NF,BCNF,4NF详析

    4NF详析引言范式种类第一范式(1NF)符合1NF的关系中的每个属性都不可再分存在...范式(4NF)相关概念介绍多值依赖Teaching模式中存在的问题平凡函数依赖和非平凡的函数依赖多值依赖与函数依赖的区别了解4NFPoint总结...

    数据库范式设计实验报告.doc

    中国海洋大学实验报告 年 月 日 姓名 系年级 2012级 专业 计算机学号 科目 数据库 题目 通过实验体会关系数据理论,函数依赖以及范式。 实验要求 1. 设计一个关系,使之满足2NF而不满足3NF; 设计一个关系,使之满足...

    数据库六大范式详解

    文章中的一些概念候选码主属性函数依赖完全函数依赖部分函数依赖传递函数依赖什么是范式范式的分类第一范式(1NF)第二范式(2NF)第三范式(3NF)巴斯-科德范式(BCNF)第四范式(4NF)第五范式(5NF) 文章中的...

    数据库设计范式.doc

    所谓第一范式(1NF)是指数据库表的每一列都是不可分割的基本数据项,同一列中不能 有多个值,即实体中的某个属性不能有多个值或者不能有重复的属性。如果出现重复的 属性,就可能需要定义一个新的实体,新的实体由...

    数据库设计反范式.pdf

    范式 1.1 1NF-3NF 定义 1NF确保原⼦性(Atomicity)原⼦性的粒度、原⼦性的价值(1范式:单值,并且把值当做单值⽤,建议不要把值 拆开) 2NF检查对键的完全依赖价值在在于控制数据冗余和查询性能 3NF检查属性的独⽴性 ...

    对数据库三大范式及BC范式的理解

     不能是多值属性,如果存在,应该建立一个实体,而让此属性与其存在1对多的关系)  不能是重复属性    2.第二范式:任何非关键字段不能部分依赖任一侯选关键字(即必须完全依赖)  表中必须存在侯选关键字...

    有关系模式R(ABCDE),回答下面几个问题:

    有关系模式R(ABCDE),回答下面几个问题: (1)若A是R的候选码,具有函数依赖BC → DE,在 什么条件下 R是BCNF?...(2):对于左侧为多属性的函数依赖集求所有候选码 ①:F={A →B,BC →D,DE →A} ②:令G=F-

    精髓Oralcle讲课笔记

    --求出sal>1200的平均值按照deptno分组,平均值要>1500最后按照sal的倒序排列 60、select ename,sal from emp where sal > (select avg(sal) from emp); --求那些人的薪水是在平均薪水之上的。 61、select ename...

    数据库设计三大范式.pdf

    第三范式的条件:关系模型满⾜第⼆范式,所有⾮主属性对任何候选关键字都不存在传递依赖。即每个属性都跟主键有直接关系⽽不是间接 关系,像:a-->b-->c。⼀般数据库设计中,⼀般要求达到3NF,第四第五较少涉及。 ...

    ch10数据依赖与关系模式规范化1

    第10章数据依赖与关系模式规范化目录 Contents10.1 概述10.2 函数依赖与范式10.3 多值依赖与范式10.4 模式分解理论10.1 概述10.1

    数据库设计范式(实例).doc

    第一范式(1NF):在关系模式R中的每一个具体关系r中,如果每个属性值 都是不可再分的最小数据单位,则称R是第一范式的关系。例:如职工号,姓名,电话号 码组成一个表(一个人可能有一个办公室电话 和一个家里电话...

    详谈数据库泛型:第一、二、三、四和BCN范式

    6 第四范式:消除表中的多值依赖 7 详细举例 1 什么是数据库泛型? 数据库泛型就是数据库应该遵循的规则。数据库泛型也称作数据库范式。数据库范式是数据库设计需要满足的一些规范。满足这些规范可以使数据库变得...

    数据库范式(1NF_2NF_3NF_BCNF)详解

    第二范式-(多对多关系 以学号和教师编号为主键的表)当一张表中有多个字段作为主键时,非主键的字段不能只依赖部分主键(学生姓名依赖学号,二不依赖组合主键);解决方法分成三张表 第三范式-不能存在传递依赖(有不...

    依赖注入与jsr

    依赖注入(控制反转的一种形式),它是Java开发主流中一个重要的编程范式(思维方式)。简单的说,使用DI技术可以让对象从别处获得依赖项,而不是由它自己来构造。使用DI有很多好处,它能降低代码之间的耦合度,让...

    Mysql数据库设计三范式实例解析

    三范式 1NF:字段不可分; 2NF:有主键,非主键字段依赖主键; 3NF:非主键字段不能相互依赖; 解释: 1NF:原子性 字段不可再分,否则就不是关系数据库;...如果实体中的某个属性有多个值时,必须拆分为不同的

    6G研究白皮书 -6G 无线网络:愿景、使能技术与新应用范式 .rar

    为了满足这些需求,6G 无线通信网络将依赖于新的使能技术,并将出现新的四大范式转换。新颖的空口与传输技术、网络架构至关重要,包括波形设计、多址接入、信道编码、多天线技术、软件定义网络、网络功能虚拟化以及...

Global site tag (gtag.js) - Google Analytics