在几乎任何正式结构化的信息集中,您要么从头到尾阅读,要么偶尔从尾到头阅读(例如街道地址)。但是在 SQL 中,尤其是 SELECT 查询中,为了正确理解它的意思是你必须从中间开始,从 FROM 子句开始。这会使长查询非常难以阅读,特别是如果它包含嵌套的 SELECT 查询。
通常在编程中,当某些事情似乎没有任何意义时,背后有一个历史原因。从 SELECT 而不是 FROM 开始是没有意义的。有谁知道这样做的原因?
我认为就英语句子的结构而言,SQL 语句的结构方式是合乎逻辑的。基本上
I WANT THIS
FROM HERE
WHERE WHAT I WANT MEETS THESE CRITERIA
我认为这没有多大意义,至少用英语来说,说
FROM HERE
I WANT THIS
WHERE WHAT I WANT MEETS THESE CRITERIA
SQL Wikipedia 条目简要描述了一些历史:
在 1970 年代,IBM 圣何塞研究实验室的一个小组开发了 System R 关系数据库管理系统,该系统基于 Edgar F. Codd 在他有影响力的论文“大型共享数据库的数据关系模型”中介绍的模型。IBM 的 Donald D. Chamberlin 和 Raymond F. Boyce 随后创建了结构化英语查询语言 (SEQUEL)来操作和管理存储在 System R 中的数据。缩写词 SEQUEL 后来更改为 SQL,因为“SEQUEL”是 UK-总部位于霍克西德利飞机公司。
原始名称明确提到了English,解释了语法。
再深入一点,我们发现了FLOW-MATIC编程语言。
FLOW-MATIC,原名 B-0(Business Language version 0),可能是第一个类英语的数据处理语言。它是由 Grace Hopper 发明和指定的,1955 年 Remington Rand 开始为 UNIVAC I 开发商业变体。到 1958 年,编译器及其文档普遍可用并在商业上使用。
FLOW-MATIC 是Common Business Oriented Language背后的灵感来源,它是仍在积极使用的最古老的编程语言之一。秉承这种精神,SEQUEL采用类似英语的语法设计(1970 年代是现代的,与 1950 年代和 1960 年代相比)。
从长远来看,“现代”编程系统仍然使用背后的古老思想访问数据库
MULTIPLY PRICE BY QUANTITY GIVING COST.
我必须不同意。SQL 语法不是由内而外的。
从第一眼看,您就可以判断查询是否会选择、插入、更新或删除数据(SQL 的所有其余部分,例如 DDL,故意省略)。
回到您的 SELECT 语句混乱:SQL 的目的是声明性的。这意味着你表达你想要的,而不是你想要的方式。因此,首先说明您想要什么(您正在选择的属性列表)然后向 DBMS 提供一些关于应该从哪里查找的附加信息是很有意义的。
将 WHERE 子句放在末尾也很有意义:想象一个漏斗,顶部宽,底部窄。通过在语句末尾添加 WHERE 子句,您可以减少结果数据的数量。在底部以外的任何地方对您的查询应用限制将需要开发人员转过头来。
最后的 ORDER BY 子句:一旦数据通过漏斗,就对其进行排序。
JOINS(JOIN 标准)确实属于 FROM 子句。
分组:基本上是在数据进入另一个漏斗之前通过一个漏斗运行数据。
SQL 语法很好用。里面没有什么。也许这就是为什么 SQL 在几十年后仍然如此流行的原因。它很容易掌握和理解。(虽然我曾经遇到过一个 7 页(A4 大小)的 SQL 语句,我花了很长时间才弄明白。)
它的设计类似于英语。我认为这是主要原因。
附带说明一下,我记得 LINQ 的初始预览是直接以它为模型的(select ... from ...
)。这在后来的预览中被更改为更像编程语言(因此范围向下)。Anders Hejlsberg 特别提到了这个关于 SQL 的奇怪事实(这使得 IntelliSense 更难并且与 C# 范围规则不匹配)作为他们做出此决定的原因。
无论如何,好或坏,它就是这样,改变任何事情都为时已晚。
SQL 中子句的顺序是绝对合乎逻辑的。请记住,SQL 是一种声明性语言,您可以在其中声明您想要的内容,系统会计算出如何最好地为您获取它。第一个子句是 select 子句,您可以在其中列出结果表中所需的列。这是查询的主要目的。在说明了您希望结果的样子之后,您接下来说明数据应该来自哪里。where 子句限制返回的数据量。除非您知道数据的来源,否则考虑如何限制数据是没有意义的,因此它位于 from 子句之后。group by 子句与 select 子句中的聚合运算符一起使用,并且可以放在 from 子句之后的任何位置,但是最好考虑对过滤数据进行聚合,因此它位于 where 子句之后。have 子句必须在 group by 子句之后。order by 子句是关于如何呈现数据并且可以在选择之后的任何位置。
它与 SQL 的其他语法一致,即每条语句都以动词(CREATE
、DROP
、UPDATE
等)开头。
首先使用列列表的主要缺点是自动完成不方便(正如 Hejlsberg 所提到的),但在 1970 年代设计语法时,这并不是一个问题。
我们本可以使用类似 的语法两全其美SELECT FROM SomeTable: ColumnA, ColumnB
,但现在改变它为时已晚。
总之,SQL 的SELECT
语句顺序不是唯一的。它与 Python 列表推导完全匹配:
[(rec.a, rec.b) for rec in data where rec.a > 0]
除了语言的历史(虽然它很吸引人),我认为你缺少的是 SQL 不是告诉系统要做什么,而是告诉系统你想要什么最终结果(它会弄清楚如何去做)
说“到那个架子那边去,拿起带帽带的帽子,先是蓝色的帽子,然后是绿色的,然后是红色的,然后把它们拿给我”,这在很大程度上告诉系统如何做你想做的事。程序员认为我们认为工人非常愚蠢并且需要非常详细的说明。
SQL首先从最终结果开始,您想要的数据,列的顺序等。这非常适合构建报告的人的观点。“我想要名字,姓氏,然后是年龄,然后......”这毕竟是提出请求的目的。所以它从你想要的结果格式开始。然后它会进入您希望它找到数据的位置、要查找的标准、呈现它的顺序等。
因此,作为详细说明您希望工作人员做什么的替代方法,SQL 假定系统知道如何执行此操作,并更多地关注您想要做什么。
因此,与其学究式地告诉你的工人去这里,拿这个,把它带到那里……更像是说“我想要帽子,从 12 号架子上买,有帽带,请按颜色分类。”