SQL数据库在接收到一条SQL语句后,并不会直接执行,而是先把它当成一段纯文本进行解析。解析的核心任务分为两步:词法分析和语法分析。词法分析把字符序列拆成记号,语法分析依据规则把记号组织成树状结构,供优化器进一步处理。

什么是词法分析
词法分析也叫扫描,输入是SQL字符串,输出是一串记号(token)。常见的记号类型包括关键字(如SELECT、FROM)、标识符(表名、列名)、常量、运算符和分隔符。数据库通常使用有限状态机或正则匹配来识别这些记号。
简单词法拆分示例
以语句 SELECT id FROM user 为例,词法分析后得到:
- SELECT:关键字
- id:标识符
- FROM:关键字
- user:标识符
什么是语法分析
语法分析接收词法分析的记号流,按照SQL语法规则判断其是否合法,并构建抽象语法树(AST)。如果写错结构,比如缺少FROM,就会在这个阶段报错。
语法分析流程
- 从记号流读取首个关键字,确认是查询语句
- 解析选择列列表
- 解析FROM子句及表名
- 可选解析WHERE、ORDER BY等
- 生成AST交给后续模块
用代码模拟简易解析
下面用Python写一个简单的词法拆分示例,帮助理解记号提取过程:
# 简易SQL词法拆分示例
def lex(sql):
tokens = []
# 按空白分割,仅作演示
for word in sql.split():
if word.upper() in ('SELECT', 'FROM', 'WHERE'):
tokens.append(( 'KEYWORD', word.upper() ))
else:
tokens.append(( 'IDENT', word ))
return tokens
sql_text = "SELECT id FROM user"
print(lex(sql_text))
词法与语法分析的协作
在实际数据库中,词法分析和语法分析常由同一个解析器驱动。解析器每需要一个记号就调用词法分析器获取一个,这种配合称为“拉式”解析。最终生成的AST类似下表结构:
| 节点类型 | 内容 |
|---|---|
| Query | 根节点 |
| SelectList | id |
| From | user |
小结
理解SQL解析中的词法分析和语法分析,有助于我们写出规范语句并快速定位错误。当数据库报语法错误时,通常就是这两个阶段发现了不满足规则的输入。