关系就是集合————知道这一点只算是理解了关系模型的冰山一角。关系这种集合其实有一些非常有趣且特殊的性质,其中之一就是与SQL语言的原理密切相关的“封闭性”(closure property)。
从运算角度审视集合
关系不只是集合,它还有许多非常有趣的性质,其中之一就是“封闭性”。这个性质简单地说就是“运算的输入和输出都是关系”,换句话来说,就是“保证关系世界永远封闭”的性质。
SQL中由各种各样的关系运算符。除了最初的投影、选择、并、差等基本运算符,SQL后来又增加了许多非常方便的运算符,现在总的数量非常多。多亏了关系的封闭性,这些运算的输出才可以直接作为其他运算的输入。因此,我们可以把各种操作组合起来使用,比如对并集求投影,或者对选择后的集合求差,等等。这个性质也是子查询和视图等重要技术的基础。
在关系模型中,关系对关系运算符也是封闭的。关于这一点,从“SQL中SELECT句的输入/输出都是表”也能得到证明。SELECT子句其实就是以表(关系)为参数,返回值为表(关系)的函数。SELECT子句有时一条数据也查询不到,然而这时会返回“空集”,而不是不返回任何内容,只是以因为我们没法实际看到,所以不好确认(MySQL的SQL命令行会贴心地输出Empty set的消息)。例子中的封闭性来自数学的概念。数学中会根据“对于什么运算是封闭的”这样的标准,将集合分为各种类型。这些对某种运算封闭的集合在数学上称为“代数结构”。例如,按照对四则运算是否封闭,我们可以把集合分为下面几类:
1.群(group):对加法和减法(或乘法和除法)封闭。
2.环(ring):对加法、减法、乘法封闭。
3.域(filed):对加法、减法、乘法、除法封闭,即可以自由进行四则运算。
如果要举个关于“群”的具体示例,那么最简单的就是整数集了,因为任何两个整数之间进行加法或者减法运算,结果一定还是整数。整数集也是环,但却不是域,关于原因,看一个例子就知道了。比如1/2的结果是小数,不满足封闭性。如果将整数集扩展成有理数集或者实数集的话,那么结果就能满足域的条件了。这是因为,使用实数自由地进行四则运算后,运算结果还是实数。
实践和原理
那么,关系模型中的“关系”相当于这些代数结构中的哪一种呢?
我们回忆一下SQL中集合运算符可以发现,关系支持加法(UNION)运算和减法(EXCEPT)运算,因此它满足群的条件。关系还支持相当于乘法运算的CROSS JOIN,所以也满足环的条件。那么最后一个,除法呢?很遗憾,关系中没有除法运算符,所以不满足域的条件。
的确,SQL中没有除法运算符。但我们在1-6节中说过,它是有除法运算的定义的。因此,关系也满足域的条件。从满足运算相关特性的观点来看,关系可以理解为“能自由进行四则运算的集合”。C.J.戴特和乔·塞尔科之所以非常重视除法运算,一方面是因为它的实用性很高,另一方面则是因为他们深知只有定义了除法,才有资格成为域。
由此可见,关系模型理论具有严密的数学基础。这样的好处是,它能够直接使用集合论和群论等领域中已经得到广泛应用的研究成果。科德深知构建这样严密的理论体系是多么重要。实际上,如果UNION和连接运算的结果不是关系(表),SQL这门语言会变得非常难用。无法使用子查询的SQL——这根本无法想象。SELECT语句的执行结果是无序的,虽然乍一看很不方便,但这也是保持关系的封闭性所必需的。
综上所述,关系通过对关系运算封闭,使SQL具有了非常强大的表达能力。




