sqlparse.split拆分无结尾分号的多段SQL结果错误如何解决
无结尾分号场景下sqlparse多SQL语句拆分解决方案
sqlparse原生split方法默认仅以分号作为语句分隔标识,若前序SQL未显式添加结束分号,会将相邻的多条合法SQL识别为同一个语句块。以下是3种可行的实现方案:
方案1:使用sqlparse.parse语法解析直接拆分
sqlparse的parse方法本身会基于SQL语法结构拆分语句,不需要依赖分号作为唯一分隔符,是最简单的适配方案:
import sqlparse t_sql = """create table dmc_o2_test( stuid number(38) primary key, stuname varchar2(30) not null ) select * from dmc_o2_test;""" # parse方法会自动按语法拆分语句块 parsed_stmts = sqlparse.parse(t_sql) # 过滤空语句和空白字符 sql_list = [str(stmt).strip() for stmt in parsed_stmts if str(stmt).strip()] print(len(sql_list)) # 输出结果为2,符合预期
适用场景:绝大多数标准SQL场景,支持嵌套子查询、带注释的SQL,不会误判字符串/子查询内的SQL关键字
方案2:基于token流关键字识别自定义拆分逻辑
如果需要更高的自定义拆分规则,可以遍历解析后的token流,识别顶级DDL/DML关键字作为语句开头标识拆分:
import sqlparse from sqlparse.tokens import DDL, DML def custom_sql_split(sql_content): parsed = sqlparse.parse(sql_content) sql_list = [] current_stmt = [] for stmt in parsed: for token in stmt.tokens: token_val = str(token).strip() # 遇到顶级DDL/DML关键字时判定为新语句开头 if token.ttype in (DDL, DML) and token_val: if current_stmt: sql_list.append(''.join(current_stmt).strip()) current_stmt = [] current_stmt.append(str(token)) elif current_stmt: current_stmt.append(str(token)) # 加入最后一条未收尾的语句 if current_stmt: sql_list.append(''.join(current_stmt).strip()) return [s for s in sql_list if s] # 测试示例 result = custom_sql_split(t_sql) print(len(result)) # 输出结果为2
适用场景:需要自定义拆分规则、适配非通用SQL方言的场景,可以自行扩展支持的关键字类型
方案3:正则预处理补充分号后拆分
针对格式规整的简单SQL场景,可以用正则给行首的SQL开头关键字前补充分号,再调用原生split方法拆分:
import re import sqlparse # 匹配行首(允许前缀空白)的标准SQL开头关键字,前面插入分号 processed_sql = re.sub( r'(?<=\n)\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|TRUNCATE|MERGE)', r';\1', t_sql, flags=re.IGNORECASE ) result = [s.strip() for s in sqlparse.split(processed_sql) if s.strip()] print(len(result)) # 输出结果为2
适用场景:SQL格式规整、无注释/字符串内嵌SQL关键字的简单场景,实现成本低、执行效率高
注意事项
- 涉及存储过程、自定义函数等复杂语法时,建议扩展方案2的关键字匹配规则,或者引入对应数据库方言的专用解析器
- 若SQL存在明显语法错误,所有解析类方案的拆分准确率都会下降,建议拆分前先做基础语法校验
内容的提问来源于stack exchange,提问作者caiyi0923
相关产品推荐
相关产品推荐

