使用集值属性可以使设计冗余的数据得到存储,从而导致其属性不一致。例如,与其将教师和部门之间的关系表示为单独的关系,还不如让数据库设计人员将一组课程标识符与每个教师和一组教师标识符存储在每个部分中。(部门和教员的主键用作标识符。)当教师教哪一部分的数据被更改时,更改必须在两个地方进行:在一组教师的集合中,以及教师的一组部分。不执行这两个更新可以使数据库处于不一致的状态。只保留其中的一套,即一组教师的部门或一组部门的教师,将避免重复的信息;然而,只保留其中一套会使某些查询复杂化,而且还不清楚这两种中哪一种会保留。某些类型的非原子值可能是有用的,尽管它们应该小心使用。例如,复合值属性通常是有用的,并且在许多情况下,设置值属性也是有用的,这就是为什么在E-R模型中支持这两种属性。在许多实体具有复杂结构的领域中,强制第一个范式表示对应用程序程序员来说是不必要的负担,他们必须编写代码将数据转换成原子形式。还存在从原子表单来回转换数据的运行时开销。因此,对非原子值的支持在这些领域中非常有用。事实上,现代数据库系统确实支持许多类型的非原子值,正如我们在Chapter22中所看到的。然而,在这一章中,我们对第一范式的关系是严格的,因此,所有的域都是基本的。
1. 学生和教师的身份是独一无二的。
2. 每个学生和老师只有一个名字。
3. 所示。每个教师和学生(主要)只与一个部门联系在一起。
4. 每个部门的预算只有一个价值,而且只有一个相关的建筑。
我们重申这个定义如下:r(R)是一个关系模式。
如果在R (R)的任何法律实例中,在R的实例中,如果t1 = t2,那么之后t1[K] = t2[K],则为R (R)的一个子集k (R)。
也就是说,在任何关系r(r)的任何法律实例中,没有两个元组在属性集合K上具有相同的值。显然,如果r中的两个元组在K上没有相同的值,那么一个K值就会识别一个元组。
而超键是一组唯一标识整个元组的属性,而功能依赖则允许我们表达约束,以唯一地标识某些属性的值。
考虑一个关系模式r(r),并让α⊆r和β⊆r。
•我们说,如果在r(r)的每一个法律实例中都满足了函数依赖关系,那么函数依赖关系就会保持在模式r(r)上。
使用功能相关的符号,我们说K是一个超码的r(r)如果函数依赖K→r r(r)。
换句话说,如果r(r)的每个法律实例,对于每一对元组 t1和t2,当t1[K] = t2[K]时,也就是t1[r] = t2[r](也就是t1 = t2)。
功能依赖允许我们表达我们无法用超键表达的约束。
在第8.1.2节中,我们考虑了模式:
本月部门(ID、名称、工资、部门名称、建设、预算)功能相关的部门名称→预算持有,因为每个部门(由部门名称)有一个独特的预算金额。
我们将使用以下两种方法:ID、部门名称、名称、工资、建筑、预算,我们将用两种方式使用功能从属关系:
1。测试关系的实例,看看它们是否满足给定的函数依赖项F。
2。明确法律关系的约束。
因此,我们只关心那些满足给定的函数依赖集的关系实例。
如果我们想要约束我们自己,以满足函数依赖的集合F(R)的关系,我们说F保持r(R)。
让我们考虑图8.4的关系r的实例,看看哪些功能依赖项得到了满足。
注意:A C是满意的。
有两个图,它们的值是a1。
这些元组具有相同的C值,即c1。
类似地,两个具有A值的元组具有相同的C值,c2。
没有其他成对的不同元组具有相同的值。
然而,功能依赖关系C . A并不满足。
要知道它不是,考虑元组t1=(a2,b3,c2,d3)和t2 =(a3,b3,c2,d4)。
这两个元组有相同的C值,c2,但是它们有不同的值,分别是a2和a3。
因此,我们发现了一对元组t1和t2,这样t1[C] = t2[C],但是t1[a] = t2[a]。
一些功能依赖项被认为是微不足道的,因为它们对所有关系都感到满意。
例如,A对所有涉及属性A的关系都表示满意。
从字面上理解函数依赖的定义,我们看到,对于所有的元组t1和t2, t1[A] = t2[A],是t1[A] = t2[A]。
在图8.5的教室关系实例中,我们看到房间号的容量是满足的。
然而,我们认为,在现实世界中,不同建筑的两间教室可以有相同的房间号,但房间容量不同。
例如,给定一个模式r(A.B,C),如果函数依赖A-B和BC,保持r,则我们可以推断函数依赖关系AC也必须保持r。这是:因为,给定A的任何值,B只能有一个对应的值,对于B的那个值,C只能有一个对应的值。我们以后研究。在第8.4.1节,如何做出这样的推论。
我们将使用符号F+来表示SEF的闭包,即给定集合F可以推断的所有函数依赖的集合。ClearlyF+包含F中的所有功能依赖项。
我们能得到的更理想的正规形式之一是Boyce-正规形式(BCNF)。它消除了基于功能依赖关系可以发现的所有冗余,不过,正如我们在第8.6节中所看的,可能还有其他类型的冗余。关系模式R相对于函数依赖集F是BCNF,如果对于形式为 的F+中的所有函数依赖项,其中 R和R,至少有以下一种情况:
如果设计的每个成员构成BCNF,则设计在BCNF中。在第8.1节中,我们已经看到了一个不在BCNF:关系模式的例子,即关系模式
inst_dept(ID、name、工资、dept_name、Build、预算内)函数依赖的dept_name预算在inst_dept上保持不变,但dept_name不是超级键(因为部门可能有一些不同的说明器)。在8.1.2节中,我们发现将inst_dept分解为指导员和部门是一种更好的设计方法。指导员模式在BCNF中。
将ID包含在箭头的左侧,ID是指导员的超级键(在本例中是主键)。(换句话说,在没有非平凡的情况下,name,dept_name和salary没有id的组合不存在非生物功能依赖关系。)。讲师在BCNF中,同样,这department模式在BCNF中,因为所有重要的功能依赖关系都是有效的,例如:
Dept_namebuilding,budget
包括在箭头的左边dept_name,和dept_name是超键(和主键)出发。因此,department是BCNF。
我现在的状态一般规则分解,不在BCNF。设R是一个模式不是在BCNF。那么至少有一个非平凡的函数dependencv ,那不是一个超码的R,我们取代R在我们两模式设计:
在这个例子中,结果是 。我们需要像我们所做的那样声明规则,以便正确地处理功能依赖项,这些依赖项的属性出现在箭头的两边。这方面的技术原因稍后将在8.5.1节中讨论。当我们分解一个不在BCIF中的模式时,可能是一个或多个结果模式不在BCNF中。在这种情况下,需要进一步分解,其最终结果是一组BCNF模式。
我们已经看到了几种用来表示数据库一致性约束的方法:主键约束、函数依赖、检查约束、断言和触发器。每次更新数据库时都会测试这些约束,因此,以一种可以有效测试约束的方式设计数据库是很有用的。特别是,如果可以通过考虑just一种关系来测试函数依赖,那么测试此约束的成本就会很低。我们将看到,在某些情况下,分解为BCNF可以防止某些功能依赖项的有效测试。如果我们对我们的大学组织做了一个小小的改变。在图7.15的设计中,学生可能只有一个导师。这是因为关系设置顾问从学生到艾兹的关系是一对一的。应该做的“小”改变是,一个老师只能与一个系相关联,一个学生最多可以有一个以上的导师,但最多可以有一个来自给定部门的导师。
实现这一点的一种方法:使用E-R设计的方法之一是用三元关系集替换adveisor关系集,dept_advisor,结账的实名制教师,学生和department,E-R图指定了这样的约束:“一个学生可能有多个导师,但最多有一个对应于某一部门的导师”。
使用这个新的E-R图,教师、离开学校和学生的模式不变.。但是,从dept_advisor派生的模式现在是:
虽然在E-R图没有指定,假设我们有,“一个教练可以作为单部顾问的附加约束。”然后,在dept_adtvisor持有下列函数依赖。
我们的设计使它在计算上难以执行这种功能依赖,我们说我们的设计不是依赖保存。因为通常认为,深度保护是可取的,我们考虑另一种正常形式,比BCNF更弱,这将使我们能够预先依赖。这种正常形式称为第三范式。
8.3.4第三范式
BCNE要求所有非无关的依赖项都是α->β,其中α是超键。第三范式(NF)通过允许某些非平凡的功能依赖项(而不是超键)稍微放松了这个约束。我们定义3nf之前,我们回想一下,一个候选键是一个最小的超键——也就是说,一个超码也是一个超码的没有适当的子集关系模式我在第三范式对锦鲤的函数依赖如果所有函数依赖在F+的形式从α->β,其中α⊆ R和β⊆ R,至少其中一项是:
α->β是一个微不足道的函数依赖项。
α是β的超级键,
每个属性A在β−α包含在R的候选键中。
注意,上面的第三个条件并不是说单个候选键必须包含B中的所有属性。
年代;B中的每个属性A可以包含在不同的候选键中。
前两种选择与BCNF定义中的两种替代方法相同。3NE定义的第三种选择似乎很不直观,它为什么有用并不明显。从某种意义上说,它代表了BCNE条件的最小松弛,这有助于确保每个方案都有一个对3NE的依赖分解。当我们研究分解为3NF时,它的目的会变得更清晰。注意,任何满足BCNF的方案也满足3NF,因为它的每个功能依赖项都满足前两种选择之一。因此,BCNF是比3NE更严格的正规形式。3NF的定义允许在BCNF中不允许某些功能依赖。在BCNF中只满足3NF定义的第三种选择,但在3NE允许。现在,让我们再次考虑dept-advisor关系集,它具有以下功能依赖性:在第8.3.3节中,我们讨论了函数依赖项+ ID H dept.name导致了dept-advisor模式,而不是BCNF注意到这里有一个:dept.name和β。因为函数依赖。ID, dept.name ID持有dept-advisor,属性dept.name包含在候选密钥中。因此,顾问在BNF。我们已经看到了在BCNF和3NF之间必须进行的权衡,因为没有详细描述BCNF设计。这些在第8.5.4节中有更详细的描述。
8.3.5高等范式形式
使用功能依赖来分解模式可能不足以避免某些情况下不必要的信息重复。请考虑一下教师的entity-set定义的一个细微的变化,我们记录每个教师的孩子的名字和一组电话号码。电话号码可能
被多人分享。因此,电话号码和child-name将是多值属性。按照我们从ER设计生成模式的规则,我们将有两个方案,分别针对每个多值属性phone-number和child-name。
(ID. Child-name) (ID, phone-number)
如果我们把这些计划结合起来。
(ID. Child-name, phone-number)
我们会发现结果是在BCNF中,因为只有非平凡的功能。因此,我们可能认为这样的组合是一个好主意。然而。这样的组合是一个坏主意,我们可以看到,以一个有两个孩子和两个电话号码的老师为例。举个例子,让带着ID99999的指导有两个孩子叫“大卫”和“威廉”还有两个电话号码,512-555-1234和512-555-4321。在组合方案中,我们必须对每个依赖者重复一次电话号码:
(99999, 大卫,512-555-1234)
(99999, 大卫,512-555-4321)
(99999,威廉,512-555-1234)
(99999,威廉,512-555-4321)
如果我们不重复电话号码,并且只存储第一个和最后一个元组,我们就会记录下依赖的姓名和电话号码但是元组意味着David对应的是512-555-1234,而William对应的是512-555-4321,我们知道,这是不正确的。因为基于功能依赖关系的正常表单不足以处理这样的情况,所以已经定义了其他依赖关系和正常形式。我们将在第8.6和8.7节中讨论这些问题。我们在我们的示例中已经看到,作为BCNF或3NF的测试方案的一部分,能够系统地解释函数依赖关系是很有用的。
8.4.1一组功能依赖项的关闭。
我们将看到,给定一组我的功能依赖于一个计划,我们可以证明某些其他函数依赖也坚持我们说这样的函数依赖的计划是“逻辑上隐含”f .测试正常形式时,没有充分考虑给定的函数依赖集;更确切地说,我们需要考虑所有支持该方案的功能依赖关系。
当我们给定A→B遵从这个函数:t1[B]= t2[B]