深入数据库理论:查询语言
“Theory is when you know everything but nothing works. Practice is when everything works but no one knows why. In our lab, theory and practice are combined: nothing works and no one knows why”
– 理论就是当你知道一切却没有一样东西好使,实践就是所有东西都好使却没人知道为什么。在我们的实验室中,理论和实践是相结合:没有一样东西好使,也没人知道为什么 :)
很多理论可能仅限于学术研究和考试内容 :| 这么多年的工作也训练出了自己的一套工作方法,理论再好还是得服务于实践,不然也只能束之高阁。但通过对理论的系统梳理,也了解了自己的工作方法在理论中处于怎样的位置,以后实践中遇到问题应该去哪里寻找答案。
注:为了熟悉各种名词的英文说法,所以很多概念都用英文表示。
1.理论基石:逻辑
逻辑是数学的基石,当然也是我们写程序、程序执行的基石。没有逻辑,数据库查询的执行无从谈起。因此,要学习数据库查询的内部是运转的,就要从逻辑开始学起。重点了解量词的使用和从循环角度思考,这对于后面学习查询理论时是很有用处的!
1.1 命题逻辑(Propositional Logic)
命题(Proposition)就是一个能够判断真假的声明式语句。例如,华盛顿是美国的首都,1+1=2等。用来表示命题的字符就叫做命题变量(Propositional variable)。已存在的命题可以通过与或非等逻辑运算符组成新的命题,也叫做复合命题(Compound proposition),这些逻辑运算符也叫做连接符(Connective)。
“if p, then q”这种两个命题组合起来叫做条件语句(Conditional statement),表示为: a→b 。要注意的是,当p为False时,不论q真假如何,整个条件语句都为True。举个例子,当你考100分时,那么你拿到A。当你没考100分时,不论你是否拿A,整个条件语句都是True,因为条件语句的判断条件没有发生。
编程语言中的if语句
逻辑中的条件语句与编程语言中的if语句是完全不同的。例如Java中的if-then语句,if中的确是一个可以判断真假的命题,但是then中是一个动作而不是一个命题或事实。这也是SICP中提到过的,编程语言与数学语言的区别,你不可能像推导数学公式一样让程序一步步自动推导出下一步要执行的语句。具体请参考:《程序员修炼之路-(1)基础(下):正确性证明 》。
在所有Case下都具有相同真值的复合命题就叫做逻辑等价,表示为: p≡q 。通过真值表(Truth table)我们可以得到一些简单命题的逻辑等价性,例如其中很重要的一组等价就是De Morgen定律:
¬(p∧q)≡¬p∨¬q
¬(p∨q)≡¬p∧¬q
当我们掌握了这些基本符合命题的等价性后,就可以抛弃真值表,而用它们去推导更加复杂的复合命题的真值了。因为对于更加复杂的复合命题来说,用真值表的方式实在太麻烦了。
一个复合命题只要在一种Case下是True,我们就是它是Satisfiable的。
1.2 谓词逻辑(Predicate Logic)
前面讲了这么多命题的知识,其实命题并不能充分地表达出数学语言或自然语言中语句的含义。因为命题只是粗略地表示出一整句的真值,并与另一语句进行逻辑运算,获得组合后的真值。所以现在就引出更为强大的谓词逻辑(Predicate logic),正如其名,我们将一个语句分为主语(Subject)和谓语(Predicate)。例如,语句“变量x大于3”分为主语“变量x”和谓语“大于3”。可以用P(x)表示这个语句,P(x)就叫做命题函数(Propositional function)。一旦变量x分配了值,语句P(x)就成了一个命题,就可以计算其真值了。
1.3 量词(Quantifier)
除了给变量分配值的方式外,还可以用量化(Quantification)的方式将命题函数转换为命题。量化表示了谓词在何种范围内为真,例如所有、一些、没有等等,最常见的Universal和Existential量化表示为: ∀xP(x) 或 ∃xP(x) 。符号 ∀ 表示P(x)对于域中的所有x, ∃ 表示域中存在一个x使得P(x),它们就叫做量词(Quantifier)。要想成功把谓词逻辑通过量化转换为命题,就要满足:
- 域(Domain):当使用量词时,必须指定变量的值域。
- 绑定(Bound):被量词限制变量加做被绑定了(Bound),被量词限制的逻辑表达式部分被称作范围(Scope),未被量词绑定或赋值的变量被称作自由变量(Free)。所有变量必须被绑定或赋值。
例如, ∀x(x<0−>x2>0)