14.1 概述
再重复一下我在第10章讲过的内容,我确信先了解关系模型,然后再学习SQL会比先学习SQL再学习关系模型要容易些。其原因是如果先学习SQL再学习关系模型的话,会需要很多未了解的知识(因此本书才按照这样的结构来安排,就像在第1章中介绍的一样)。实际上,我相信并不是任何人都真正了解SQL的方方面面,只是知道了这种语言,而不是真正了解它的实质。SQL如此庞大、如此复杂、如此特别、如此非正交(此处忽略了它的逻辑差异、不一致性、矛盾等1),经过分析后我不得不相信SQL是很难教会的。我不止一次地遇到过这样的情况,即我向很多SQL专家请教一些技术问题的答案时(我曾拜访过SQL标准委员会的成员或曾经的成员),往往要等上一些时间才能获得答案,即使答案是现成的(但不总是这样的),这些答案也不保证一直是正确的。
无论如何,我希望你从上面的叙述中可以了解到,为什么人们(就像我自己)都拒绝把现在主流的“关系型”产品看作是关系型的。实际上它们是SQL型产品:它们支持的基本数据对象是SQL表,不是关系。它们支持的运算符可以处理SQL表,而不能处理关系。但令人遗憾的是(不能说是奇怪的),我一直坚信真正的关系型DBMS应该远远超越只支持SQL的DBMS(不仅是从可用性的角度超越,而且要在易实现性、优化性和良好的性能方面来超越)。我简短地阐述一下。
可用性:一个不可否认的事实就是,SQL要比关系模型复杂得多,而且它也没额外提供一些有用的功能。实际上严格来讲,它提供的功能要比关系模型少,因为它完全不是关系型的(参见第7章中关于此概念的讲解)。
优化和性能:首先我需要解释一下优化器的概念,优化器的功能之一就是完成表达式的转换,即将表达用户原始请求的表达式转换为另一种逻辑上与其等价的表达式,并且要保证得到等价的结果,而且性能要优于原始的表达式(至少这是我们所希望的)。(我已经在本书中的某些地方提到过这个概念,比如第1章。)也就是说,对于关系来说可以完成很多这样的转换,但是对于带有重复行的表来说不能完成这么多的工作,如果考虑列的顺序、考虑空值则不能完成众多的转换。换句话说,这些非关系型的特征(重复行、列序、空值)都是阻碍优化的重要因素,因此会影响性能,另一方面,这些特征也会使优化器更加复杂,所以很难实现。
注意:
这里我又提出了几点,首先,你需要理解“不存在两个等价的SQL”(我在第10章曾提到过)。
目前没有一款商业产品完全支持这个标准(实际上,如果考虑到不一致性和我上面提到的那些,没有一款产品能做到这一点)。
同时,每款产品都具有自身特有的一些特征,而这些特征并不是标准的一部分。
而且,这个标准明显遗留了一些需要在特定产品中解决的问题。(例如,为结果中的列命名,否则这个列就没有名字。可以参照第10章练习10.3的答案。)你认为这些产品都能恰好采用相同的方法来解决这些问题吗?
我感觉还有义务提一下,即使从纯粹的正规编程语言角度来说,以任何标准衡量SQL的设计都是很糟糕的。实际上对于语言设计的好坏已经建立起评价标准,我记得应该是:通用性、简洁性、完整性、相似性、可扩展性、开放性和正交性2,但似乎没有任何证据可以证明SQL的设计符合上述特性。
但有趣的是,为什么市场上喜欢使用SQL,而不使用关系模型呢(对于此事我有自己的观点,但我不会在这里表明)。迄今为止,无论如何我们都还不得不学会忍受这种选择的结果。即便这样,对于SQL表的设计和SQL运算符的使用等规则的研究仍然是人们感兴趣的,当然目的是使整个系统看上去与真正的关系型一样。实际上我在第11章曾经提到过,这些规则在SQL and Relational Theory一书中用很大篇幅进行了介绍。然而不幸的是,由于SQL语言和当前SQL产品的设计原因,采用这样的规则反而会有些痛苦。当然,实际上它也没有被广泛采用。尽管如此,我还是强烈推荐使用它。