SQL 像英语是个善意的错误

我们知道,SQL 很像英语,简单的 SQL 语句直接可以作为英语读。除了 SQL 外,其它主要程序设计语言都没有这样,语法中就算有英语单词也仅仅是作为某些概念或操作的助记符而已,写出来的是形式化的程序语句 (statement) 而不是英语句子(sentence)。而 SQL 不同,它会把整个句子写成符合英语习惯的形式,还会补充很多不必要的介词,比如 FROM 作为语句的运算主体却被写到后面,GROUP 后面要写一个多余的 BY。

为什么会这样?很容易想到的理由是希望非程序设计人员也能使用。用户只要会读写英语,就可以写出 SQL 来查询数据。这显然是个善意的初衷,但结果却不尽如人意。绝大多数业务人员只会用 SQL 写非常简单的查询,而对于这类查询,现在有强大的 BI 软件能提供更为便捷直观的可视化界面来协助,并不需要直接手写语句,这个设计初衷就失去意义。反过来, 经常使用 SQL 做运算的仍然是程序员,SQL 还是一种编程语言,像不像英语对于程序员理解并没有多大差别,反而会带来不小的困难。

事实上,SQL 是一种语法非常严格的语言,语句中任何一点不合规的地方就会被数据库拒绝,使用者必须认真学习并遵守其语法规则,这和其它程序设计语言并没什么两样。而自然语言真正的优势在于具有模糊性,可以一定程度接受不严格的语法,但 SQL 并没有支持这一点,在发明 SQL 那个年代也实现不了这个特性。

像英语的好处体现不了,反而有不少坏处,将语法设计得像自然语言,看起来容易掌握,其实恰恰相反。

贴近自然语言带来的主要坏处是非过程性。程序逻辑一般是分步执行的,用变量记录中间结果,供后面的步骤使用。但自然语言不是这样,两句话之间的引用关系靠少量几个固定的代词维系,不精确也不方便。所以会把针对同一个主语的动作尽量拼到一句话中,这样就不必借助代词了。在 SQL 中的对应表现就是在一条语句中配有多个动作,SELECT、WHERE、GROUP 这些本来是无关的动作,在其它程序语言中通常会设计成多个函数,但在 SQL 中都会设计成语句的子句。还有,像 WHERE 和 HAVING 根本是一个意思,只对针对的对象不同,在拼到一个句子中就要采用两个词以示区别,让人费解(很多初学者会对 HAVING 很晕)。

实在一句话无法描述的复杂情况,在自然语言中就会使用从句了。这在 SQL 中的表现就是子查询,还可能出现多层嵌套的子查询,这种现象在其它程序设计语言中是不常见的。而且,子查询也要像自然语言,每次都要有个 SELECT...FROM,就会让人觉得非常啰嗦,代码变得长。

分步是降低理解和执行难度的有效办法。本来挺简单分几步能做到的事情,如果不分步就会很绕。可以想象,如果老师要求小学生做应用题时只能列一个算式完成,小朋友们会多么苦恼(当然,不乏一些聪明孩子搞得定)。

比如我们要找出销售额超过平均值两倍的客户,自然思维方式就是先计算出销售额的平均值,再找出销售额超这个值两倍的客户,两个语句完成。而 SQL 的写法就需要用子查询写成更长的一句。这个例子还算好懂,只有两层,一般自然语言的从句用来描述两层关系的理解难度还可以接受,但实际复杂的查询涉及到三五层的比比皆是,严重增加理解难度。

不提倡分步,就会导致单句 SQL 很长。程序员面临的复杂 SQL 语句,很少以行计,经常是以 K 计。而同样的 100 行代码,分成 100 个语句还是只有 1 个语句,其复杂度完全不是一个级别的。这种代码理解起来非常困难,好不容易写出来,过两个月后自己都读不懂,而且太长不分步的单句非常难以调试,开发周期也更长。

关于过程性,业界有个说法,SQL 是声明式语言,用户只要关心要什么,而不必关心怎么做,数据库会自动找解决方案,这档的语言不需要支持过程性。我们在前面已经批判过这个说法。

数据库厂商应该是也发现了 SQL 缺乏过程性的问题,所以后来增加了 CTE 语法来弥补,相当于提供了可以命名的中间变量。存储过程也相当于可以分步执行 SQL,有了分支循环甚至子程序。结果还是要回到过程式语言的老路,那还不如直接就设计成这样。

对于程序语言来说,好的分步计算机制带来的易用性要远远超过长得像自然语言。

更多问题前往乾学院探讨交流!

相关推荐
香气袭人知骤暖11 小时前
SQL慢查询常见优化步骤
android·数据库·sql
Star Learning Python11 小时前
MySQL日期时间的处理函数
数据库·sql
醇氧15 小时前
SqlLogInterceptor mybatis配置打印SQL
java·sql·mybatis
清风拂山岗 明月照大江15 小时前
MySQL进阶
数据库·sql·mysql
知识分享小能手16 小时前
Oracle 19c入门学习教程,从入门到精通,SQL*Plus命令详解:语法、使用方法与综合案例 -知识点详解(4)
sql·学习·oracle
永远是我的最爱18 小时前
基于ASP.NET的图书管理系统的设计与实现
前端·后端·sql·visual studio
阳光九叶草LXGZXJ20 小时前
达梦数据库-报错-06-[-502]OUT OF TEMPORARY DATABASE SPACE(临时表空间不足)
linux·运维·数据库·sql·学习
阳光九叶草LXGZXJ20 小时前
达梦数据库-报错-05-Server Mode invalid(服务器模式不匹配)
linux·运维·数据库·sql·学习
一起养小猫21 小时前
智纺云ERP开发实战
java·css·sql·spring·html
二哈喇子!21 小时前
数据库如何建表
数据库·sql·mysql