2.3 一致性约束
每个关系变量都受制于一系列一致性约束,我们也可以把它们简称为约束。首先,我们在“关系和关系变量”这一节中已经知道,任何一个给定的关系变量都被约束为一个确定的类型(具体来说,是一个确定的关系类型),也就是说,在定义关系变量的时候,这个类型也就确定了。例如,我们再来看看供应商关系变量S的定义。11[11]
VAR S BASE RELATION
{ SNO CHAR , SNAME CHAR , STATUS INTEGER , CITY CHAR }
KEY { SNO } ;
如你所见,这个定义清晰地表明了关系变量S属于类型RELATION {SNO CHAR, SNAME CHAR, STATUS INTEGER, CITY CHAR}。而且,具体来看它还表明了属性SNO、SNAME、STATUS和CITY分别是CHAR、CHAR、INTEGER和CHAR这几种数据类型。注意:后一种约束—给每个独立属性的约束,有时候被称为“属性”约束,本段就是一个很好的例子。
我再次重申一遍,任何一个关系变量(任何一个属性更是如此)都被约束为某种类型。但是关系变量同时也会被很多其他的约束所限制,这些约束通常都是使用Tutorial D的表达式明确写出CONSTRAINT声明从而实现的。12[12]下面举几个简单的例子希望能帮助大家理解(如果你需要更多的解释说明,请参阅《SQL and Relational Theory》)。
CONSTRAINT CX1 IS_EMPTY ( S WHERE STATUS < 1 ) ;
CONSTRAINT CX2 IS_EMPTY ( S WHERE CITY = ‘London’ AND STATUS ≠ 20 ) ;
CONSTRAINT CX3 IS_EMPTY ( ( S JOIN SP ) WHERE STATUS < 20 AND PNO = ‘P6’ ) ;
现在“第三宣言”中要求所有的约束都必须在声明边界上被满足(“立即检查”)。换句话说,从逻辑上讲,对于任何有潜在可能会违反“宣言”的声明,在它约束时都会被立刻重新检查一次。13[13]或者我们也可以说得有趣一点,它们是“在分号处”被检查的。因此,与SQL标准版本或其他特定的SQL产品不同,一致性检查从来都不会被推迟到执行结束或者执行COMMIT(提交)操作的时候。
最后请注意,有时为了方便,我们对于给定的关系变量R的“全局”约束,这里要强调是针对“关系变量”的全局约束,指的是所有涉及到关系变量R的约束的逻辑AND(与)。而有时为了方便,我们对于给定的数据库的“全局”约束,这里要强调是针对“数据库”的全局约束,指的是所有涉及到该数据库中任意关系变量的约束的逻辑AND(与)。
更新每次都是集合更新
尽管这个观点尽人皆知,但还是值得我们再次强调,在关系模型中的每次更新都是集合更新(更好的说法是:每次都是“关系”更新)。我们换句通俗点的话来说,INSERT操作给目标关系变量插入了一系列数组,DELETE操作将一系列数组从目标关系变量中删除。而更广义地来讲,关系赋值将一系列数组值赋给了目标关系变量。当然,我们经常会这么说(例如)“插入某某数组”,确实,我在这本书里也会时不时这样说,但是这种说法确实是很不严谨(虽然比较方便)的。不论如何,这里我要说的重点在于一致性约束的检查要在“所有的”更新步骤(包括与之相关的补偿性操作,如果有的话)全部完成后进行。换句话说也就是从逻辑上讲,一个集合级别的更新一定不能被当作一系列单独数组级别的更新来对待。
两个重要的原则
现在我要在此特别强调2个重要的原则,这2个原则对于巩固更新(尤其包括视图更新)的概念非常重要。第1条原则也被称为黄金法则。
定义:黄金法则规定所有的数据库都不能违反它自己的全局数据库约束。
显然,由此条法则我们可以立刻推导出下面的规则:所有的关系变量都不能违反它自己的全局关系变量约束。简单来讲,就如同我所强调过的,约束必须在声明边界上被满足。我再次重申,请尤其注意,这条法则无论是对视图,还是对基础关系变量,都同样适用。
第2条原则被称为“赋值原则”。
定义:“赋值原则”规定当值v被赋给变量V之后,比较表达式v=V的结果必须为TURE。
这条原则适用于所有的赋值操作,实际上,相信你也察觉到了,它基本上就是赋值本身的“定义”,不过就本文而言,它尤其能够适用于关系赋值。当然也请再一次注意,这条法则无论是对视图,还是对基础关系变量,都同样适用。