基于Pyparsing解析含UNION/EXCEPT的复杂SQL Select遇字典覆盖问题
解决SQL复合查询解析结果覆盖问题的语法调整方案
问题根源
你当前的语法规则没有对UNION/EXCEPT这类复合操作进行分组绑定,导致多个SELECT语句的同名字段(如columns、from)被重复赋值覆盖,from字段因累加逻辑堆在一起,最终输出结构混乱。
核心调整思路
- 将单个完整SELECT语句封装为独立的
select_core语法单元,确保每个SELECT的columns、from、where_expr能被完整捕获为独立字典。 - 把复合操作符(UNION/EXCEPT)和后续的
select_core绑定成一组,明确标记操作符和对应子查询的关联关系。 - 顶层规则区分主查询(第一个SELECT)和后续所有复合操作,分别映射到
select_core和compound_operation字段。
具体代码调整(以pyparsing为例)
假设你基于pyparsing的select_parser.py改造,修改核心语法规则如下:
from pyparsing import CaselessKeyword, Group, ZeroOrMore # 1. 确保你已定义好完整的select_core结构(包含columns、from、where_expr) # 示例select_core定义(需根据你的现有代码适配): # select_core = (CaselessKeyword("SELECT") + columns + Optional(CaselessKeyword("FROM") + tables) + Optional(CaselessKeyword("WHERE") + where_expr)) # 2. 定义复合操作符 compound_operator = CaselessKeyword("UNION") | CaselessKeyword("EXCEPT") # 3. 定义复合操作单元:将操作符和子SELECT绑定为一组,标记字段名 compound_operation = Group( compound_operator("operation") + select_core ) # 4. 顶层复合查询规则:主SELECT + 零个或多个复合操作 compound_select = select_core("select_core") + ZeroOrMore(compound_operation)("compound_operation")
效果验证
解析目标SQL后,调用parseResults.asDict()会生成你期望的结构化字典:
{ 'select_core': { 'columns': [{'col': {'col': ['x']}}], 'from': [{'table': [['xyz']]}], 'where_expr': [{'col': ['x']}, '=', '1'] }, 'compound_operation': [ {'operation': 'UNION', 'columns': [{'col': {'col': ['y']}}], 'from': [{'table': [['abc']]}], 'where_expr': []}, {'operation': 'EXCEPT', 'columns': [{'col': {'col': ['z']}}], 'from': [{'table': [['pqr']]}], 'where_expr': []} ] }
关键说明
- 用
Group()包裹复合操作单元,确保每个UNION/EXCEPT和对应的子查询被视为一个整体,不会和主查询的字段混淆。 - 通过字段标记(如
("operation")、("select_core"))明确指定字典的键名,让解析结果直接映射到你需要的结构。
内容的提问来源于stack exchange,提问作者Sheldon
相关产品推荐
相关产品推荐

