You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用正则捕获含0个或多个UNION的单条SQL语句中的多个SELECT查询

嘿,我懂你遇到的问题了——想用正则把带UNION的多段SELECT语句拆分开,结果原来的正则因为贪婪匹配把整个语句当成了一个,确实头疼。咱们来一步步搞定这个:

问题根源:贪婪匹配的坑

你原来用的SELECT[\s]*.*from[\s]*里,.*是贪婪模式,它会尽可能多地匹配字符,从第一个SELECT开始,一直吃到最后一个from才停下,自然就把整个多UNION的语句当成了一个匹配项。

解决方案:非贪婪匹配+正向断言

针对你的场景(简单的UNION分隔、无复杂嵌套的SELECT),可以用非贪婪匹配结合正向断言来精准捕获每一段SELECT:

基础版正则(适配UNION)

SELECT\s.*?(?=\sUNION\s|$)

增强版正则(适配UNION/UNION ALL)

如果你的SQL里可能出现UNION ALL,可以调整成:

SELECT\s.*?(?=\sUNION(?:\sALL)?\s|$)

正则各部分解释

  • SELECT\s:匹配SELECT关键字,后面跟至少一个空格(避免误匹配类似SELECTION这类包含SELECT的单词)
  • .*?:非贪婪模式的任意字符匹配,会尽可能早地停止,而不是一直吃到最后
  • (?=\sUNION(?:\sALL)?\s|$):正向零宽断言,用来判断停止条件:
    • 要么后面是UNION或UNION ALL(注意前后的空格,避免匹配到字段名里的UNION)
    • 要么是字符串的结尾
测试示例(以Python为例)

用你的SQL语句来测试:

import re

sql_stmt = "SELECT A,B,C from ABC Where Z=5 and T=10 UNION SELECT * from GHI Where i=100 UNION SELECT X,Y from XYZ"
# 用增强版正则
pattern = r"SELECT\s.*?(?=\sUNION(?:\sALL)?\s|$)"
# 加上re.DOTALL处理可能的换行
matches = re.findall(pattern, sql_stmt, re.DOTALL)

for num, stmt in enumerate(matches, 1):
    print(f"第{num}段SELECT语句:")
    print(stmt.strip())
    print("---")

输出结果会是:

第1段SELECT语句:
SELECT A,B,C from ABC Where Z=5 and T=10
---
第2段SELECT语句:
SELECT * from GHI Where i=100
---
第3段SELECT语句:
SELECT X,Y from XYZ
---
注意事项:复杂SQL的局限性

如果你的SQL包含嵌套子查询、括号内的UNION这类复杂结构,正则就不太靠谱了——毕竟SQL的语法规则太复杂,正则无法处理嵌套的层级关系。这种情况下,建议用专门的SQL解析库,比如Python的sqlparse、Java的JSqlParser,它们能正确解析SQL的语法结构,比正则更可靠。

内容的提问来源于stack exchange,提问作者Choo William

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 09:19:46