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

如何使用递归Regex从以逗号替代CROSS JOIN的SQL中提取表名?

用正则提取交叉连接的表名:递归 vs 非递归方案

先明确:你要的场景不一定非要用递归,但如果是为了练手递归模式,完全可以实现。以下分两种方案说明,均针对你给出的规范SQL场景:

一、不用递归的简单方案

核心思路:先锁定FROM之后到终止关键字(ON|WHERE|GROUP BY|LIMIT)之间的内容,再从中提取每个表的核心名称。

分步实现

  1. 先匹配出FROM到终止关键字的区间:

    FROM\s+(.*?)(?=\s+(?:ON|WHERE|GROUP BY|LIMIT)\b)
    

    这个正则用正向预查(?=...)终止匹配,捕获到的分组1就是所有表项的字符串(比如table_1 AS a, table_2 AS b)。

  2. 对分组1的内容,再用下面的正则提取每个表名:

    \b(\w+)\b(?:\s+(?:AS\s+)?\w+\b)?
    

    解释:

    • \b(\w+)\b:捕获表的真实名称(比如table_1)
    • (?:\s+(?:AS\s+)?\w+\b)?:匹配可选的别名部分,不管是AS a还是直接a都能覆盖

合并成单正则(直接捕获所有表名)

如果想一步到位,开启全局匹配模式即可:

\b(\w+)\b(?:\s+(?:AS\s+)?\w+\b)?(?=(?:\s*,\s*\b\w+\b(?:\s+(?:AS\s+)?\w+\b)?)*\s+(?:ON|WHERE|GROUP BY|LIMIT)\b)

全局匹配后就能直接拿到所有表名的数组。

二、用递归模式的实现(练手专用)

递归在这里的作用是重复匹配「逗号+表项」的结构,适合理解正则递归的逻辑。以下是PCRE引擎支持的写法(Python需用regex库,PHP直接支持):

(?<=FROM\s)(?:\b(\w+)\b(?:\s+(?:AS\s+)?\w+\b)?(?:\s*,\s*(?R))?)+(?=\s+(?:ON|WHERE|GROUP BY|LIMIT)\b)

关键部分解释

  • (?<=FROM\s):正向预查,确保当前位置在FROM之后
  • \b(\w+)\b:捕获表名核心
  • (?:\s+(?:AS\s+)?\w+\b)?:匹配可选别名
  • (?:\s*,\s*(?R))?:递归整个模式,匹配下一个逗号分隔的表项((?R)代表重复整个正则的逻辑)
  • (?=\s+(?:ON|WHERE|GROUP BY|LIMIT)\b):匹配到终止关键字时停止

测试你给出的所有示例,这个正则都能准确捕获到table_1、table_2(三表场景会多捕获table_3)。

注意事项

  1. 这个正则只适用于格式完全规范的SQL,一旦出现表名带特殊字符(比如my-table)、嵌套子查询、注释等情况,直接失效——这也是为什么专业SQL解析器(比如Python的sqlparse)才是生产环境的正确选择。
  2. 递归模式依赖正则引擎支持,JavaScript等引擎不支持(?R),要注意使用场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 05:31:08