关系代数、SQL与逻辑式语言

“SQL其实是一种功能被极限阉割的逻辑式语言”我说这个话有很多人不懂,单纯会SQL的其实还好,但是上了数据库课程,学了“关系代数”之后,再面对这个问题就直接迷惑了。甚至一些原先还很懂逻辑和函数式语言的人,上完了数据库就像被洗了脑一样。

最近在一些事情的逼迫下,我好好思考了一下这个问题,终于明白了“关系代数”能把那么多人洗脑的原因。

首先我们要明确一点,“关系”也就是一阶逻辑中的“谓词”(如果你学过一些逻辑式语言就会知道他俩在很多语言里是一个东西的不同名字)。所以数据库里的“表”其实描述的就是一阶逻辑里的一些谓词关联。比如谓词表达式“是爹(我,你)”,对应到数据库里就是一张列是“爹”和“儿子”的表,其中有一行是“我”和“你”。上世纪掀起人工智能浪潮的第五代程序语言中的重要组件“知识库”其实就是这种表。不过那些表比现在主流DBMS描述的要高端一些,因为大部分DBMS表的格子里只能储存系统内置的那些类型的变量的单值,像正常程序语言那样自己定义类型,然后将值存进去,是不允许的(所以如果要构造一个product type就要把里面每个field类型做成另一个表的列,然后把对应元组在新表中的序号存在原表中作为外键,有点傻的感觉)。

知道了这一点之后你大概就会有点感觉,逻辑式语言的“推理”其实就是在知识库里的“谓词关联”上应用逻辑和推理规则,而SQL里面的“表”和那个“知识库”其实是一个东西。SQL的查询操作实际就是在构造一些逻辑表达式进行“推理”。那为什么这个东西会把很多原来明白的人洗脑呢?是因为关系代数的一些“术语”造成了混淆。

首先就是我们刚刚说的谓词,在SQL里“谓词”有另一码含义,看看网上资料都是怎么说的——IN是谓词、ANY是谓词,好像什么运算符都成了谓词。这里面有两个层次的问题,首先ANY和ALL肯定不是谓词而是量词,因为谓词表达式要返回真值,而ANY、ALL是限定辖域。所以如果有材料说他俩是谓词那肯定不对;其次IN和BETWEEN这种是不是谓词?如果它是,那我们之前说的数据表表示的是谓词关联又是怎么回事,这不是自相矛盾吗?

其实这个误解依然来源于上世纪的人工智能(符号推理)研究。在对一些命题的形式化过程中,为了在有限的程序语言特性条件下方便编程,科学家约定以返回值为布尔类型的函数描述谓词,这种函数在符号推理系统中被叫做“真值函数”。这里面当然有一些其它的限制,比如给一个真值函数传参时实参必须是同一个论域中的个体(你可以理解为论域变元=形参,个体变元=实参)。但是关系代数和SQL那帮人不管这个,在他们眼里“真值函数”和“谓词”就划了等号,因为IN和BETWEEN这些表达式返回布尔值,所以他们就直接被叫做谓词了。至于表里那些东西就再起另一套名字。所以就出现了这种非常吊诡的现象。

那么IN、EXSIST和BETWEEN这堆东西到底是什么呢?我们来一点一点分析。

首先IN和EXSIST是一类,因为它们都是作用于“表”的,之前我们说了,表其实描述的就是谓词关联,一张表里的元组就是这个谓词为真的所有变量取值。所以你可以把一张表理解为谓词表达式P(X),其中X是论域变元。那么x in P(X)其实就是对X进行“特称指定”(从编程的角度理解就是实参带入形参),从而得到一个真值。而EXSIST P(X)就是在问P(X)到底是不是satisfiability的,也就是能不能对各个变元取一组值使得P(X)为真(∃xP(x))。有些资料里把EXSIST理解为特称量词,这显然是错误的,它是一个逻辑表达式。

然后我们分析BETWEEN和它的小伙伴。如果上面的分析你看懂了你就会发现,它们和IN、EXSIST是完全不同的东西,因为它们作用于单值,也就是某个论域内的个体,而不是作用于谓词表达式。其实这有点类似于现代prover的构造——其实BETWEEN和大于号小于号一样,是一个代数系统上的判定性运算,它们基于该系统的“序”被定义。当然对于真实的数学代数系统,interesting的判定性运算有各种各样的,可以不只基于“序”定义。但是基于“序”的是最常见的一类,这些判定性运算直接提供了该系统的一些性质,可以转化为布尔值,供给prover进行推理使用。这也是真实prover将布尔推理规则用于实际数学问题的手段(当然现代prover的系统设计远远比我的说这些复杂,不过最基本的道理是一样的)。所以你可以看出,虽然这些运算符和数据表里的元组看起来样子很不一样,但它们描述的都是个体的性质,只是这里的性质是基于一个代数系统构造提供的,所以说它们确实是谓词。

分析到这里我们可以看出,所谓“关系模型”、“数据库查询语言”和高大上的“逻辑式语言”、“定理证明器”居然有着同样的本质。距离第一次领会到这些已经过了好多年,不过那种兴奋的感觉依然延续至今。数学、程序语言、计算机……一直延伸到经常使用的数据库软件,里面竟然有这么紧密又深刻的联系,数学老师原来不是骗我的啊。

 

最后再解释一下好多年前已经和人讨论过的那个话题:说SQL阉割了很多东西体现在什么地方?如果你一直在思考应该可以体会到,前面我们所说的,用“表”来表示“论域变元”有着致命的缺陷——你必须把所有真值都列出来才能真正描述一个谓词(更进一步说,表述一个概念),而这样没有任何抽象表达的能力。你无法通过几条性质描述一个论域、一个谓词,也无法基于现有的代数系统联合构造一些更复杂的代数系统(单纯缩小值域做一个subtype还是可以做到的),并且提取出它们的性质。所以SQL从功能上也就相当于国外AI推理本科课程做的搜索小玩具,它的“智能”有能力算出初高中的数学题(如果你不嫌自带的索引慢的话),但无法应对复杂的概念和抽象。其实这么多都说大了,因为SQL几乎不存在类型系统,所以它的表达能力连最简单的命令式语言(C语言?)都不如。但是其中的基础架构和思想与业内实际使用的真实工具是相同的。有许多人在摆弄自己做的玩具“SQL式语言”时无意打开了程序语言理论与机器证明领域的大门。而如何构造程序语言系统来应对数学与现实世界中复杂的抽象,从而开发出更安全的软件或推动纯数学的发展,也是一代又一代计算机学者研究的问题。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值