昨天,一位同事向我展示了以下postgres查询。我们都很惊讶它的工作原理:
SELECT* FROM mytable;
由于我最近为另一种语言编写了一个解析器,我试图更深入地理解为什么这个查询“编译”并返回与SELECT * FROM mytable;
相同的结果。
据推测,这被认为是一个有效的查询,因为在词法分析期间,postgres从输入中读取SELECT
作为标记,然后搜索下一个标记,它找到*
,依此类推 - 这或多或少是在这里发生了什么?
此外,postgres词法分析器/解析器是否恰好足以理解此查询,或者其他数据库是否理解类似的SELECT*
查询?
答案 0 :(得分:5)
通常词法分析器会在当前令牌中添加字符,直到找到一个不属于当前令牌的字符,然后退出并从之前无法继续的位置开始。
所以这里发生的事情是,词法分析器吞噬了SELECT
并看到下一个字符是*
,因为它正在收集一个单词,所以不能属于SELECT
。所以它会停止,分析SELECT
结果是一个关键字,并从它识别的*
重新开始,依此类推。这与您在其他编程语言中从4
和2*2
获得2 * 2
的原因相同。
至于它是否适用于其他数据库,这一切都取决于词法分析器的细节和语法规则。
答案 1 :(得分:3)
显然,标记化器会对空格和算术中使用的特殊字符进行标记。
以下是SELECT语句的BNF:h2database.com:
SELECT [ TOP term ] [ DISTINCT | ALL ] selectExpression [,...]
FROM tableExpression [,...] [ WHERE expression ]
[ GROUP BY expression [,...] ] [ HAVING expression ]
[ { UNION [ ALL ] | MINUS | EXCEPT | INTERSECT } select ] [ ORDER BY order [,...] ]
[ LIMIT expression [ OFFSET expression ] [ SAMPLE_SIZE rowCountInt ] ]
[ FOR UPDATE ]
答案 2 :(得分:2)
据我所知,SQL跳过解析空白区域,因此你可以SELECT*FROM or SELECT * FROM
它基本相同。
它还使用`
和'
来了解它是什么。因此,SELECT * FROM myTable WHERE id = my string
将是一个无效的查询,因为并且不理解“字符串”。