如何运用正则表达式在SQL解析中实现复杂查询条件的匹配?

2026-04-12 01:021阅读0评论SEO资源
  • 内容介绍
  • 文章标签
  • 相关推荐

本文共计1133个文字,预计阅读时间需要5分钟。

如何运用正则表达式在SQL解析中实现复杂查询条件的匹配?

实际场景1 - 使用实时表的+由于公司发展需要,需要对SQL进行改造装配,需要一些比较奇妙的正则表达式来处理。由于公司采用的是基于Presto的阿里云收费平台ADB,所以以下内容以ADB语法为主。


实际场景1 -WITH临时表的拆分



因为公司发展需要,要对sql进行改造拼装,借此需要一些比较奇葩的正则表达式来处理。



由于公司采用的是基于Presto的阿里收费平台ADB,所以一下以ADB语法作为讲解。



假设有一个sql如下:



WITH tmp1 AS ( select xxx ), tmp2 AS ( select xxxx ), tmp3 AS ( select xxxx ) SELECT * FROM tmp1 我们需要提取到with临时表部分,然后将其跟 "SELECT * FROM tmp1" 分离开来,这时候方法如下: public static void main(String[] args) { // 正则表达式 String formatPattern = "(with[\\s\\S]+as?\\s*\\([\\s\\S]+\\))\\s*select"; // 待匹配字符串 String sql = "WITH tmp1 AS ( select xxx ), " + "tmp2 AS ( select xxxx ), " + "tmp3 AS ( select xxxx ) " + "SELECT * FROM tmp1"; Pattern pattern = Pattern.compile(formatPattern); Matcher matcher = pattern.matcher(sql.toLowerCase()); int selectLen = "select".length(); if (matcher.find()) { String withFragment = matcher.group(); if (!StringUtils.isEmpty(withFragment)) { if (withFragment.length() > selectLen) { int lastSelectIndex = withFragment.length() - selectLen; sql = sql.substring(lastSelectIndex); withFragment = withFragment.substring(0, lastSelectIndex); } System.out.println("WITH部分:" + withFragment); System.out.println("其他部分:" + sql); } } }

输出为:



WITH部分:with tmp1 as ( select xxx ), tmp2 as ( select xxxx ), tmp3 as ( select xxxx )



其他部分:SELECT * FROM tmp1



以上,我们就可以很简单的把with部分和其他部分抽离出来了。






实际场景2 - PHP中将MySQL结果转为数组格式,格式如下:



将 var[^,]+ 替换为 => ''





如何运用正则表达式在SQL解析中实现复杂查询条件的匹配?






其他语法描述



①分组


((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)



匹配:IP



2[0-4]\d|25[0-5]|[01]?\d\d?



含义:() 括住的 是分组后内容





②后向引用



\b(\w+)\b\s+\1\b



匹配:go go



\1



含义:每个 括号 括起来的叫一个分组,分组写法 \1 \2 \3



\b(?<Word>\w+)\b\s*\k<Word>\b #?<Word>\w+ 定义,\k<Word>捕获





③位置指定(匹配指定位置前后)



\b\w+(?=ing\b) # 零宽先行断言



匹配:I'm singing while you're dancing.



(?=ing\b)





(?<=\bre)\w+\b



reading a book



(?<=\bre)





④负向位置指定



\b\w*q(?!u)\w*\b



匹配:Iraq fighting



(?!u)



含义:匹配后缀( 非 u)





(?<![a-z])\d{7}



匹配:_1234567



(?<![a-z])



含义:匹配前缀( 非 a-z)





⑤贪婪和懒惰



*?

重复任意次,但尽可能少重复

+?

重复1次或更多次,但尽可能少重复

??

重复0次或1次,但尽可能少重复

{n,m}?

重复n到m次,但尽可能少重复

{n,}?

重复n次以上,但尽可能少重复





本文共计1133个文字,预计阅读时间需要5分钟。

如何运用正则表达式在SQL解析中实现复杂查询条件的匹配?

实际场景1 - 使用实时表的+由于公司发展需要,需要对SQL进行改造装配,需要一些比较奇妙的正则表达式来处理。由于公司采用的是基于Presto的阿里云收费平台ADB,所以以下内容以ADB语法为主。


实际场景1 -WITH临时表的拆分



因为公司发展需要,要对sql进行改造拼装,借此需要一些比较奇葩的正则表达式来处理。



由于公司采用的是基于Presto的阿里收费平台ADB,所以一下以ADB语法作为讲解。



假设有一个sql如下:



WITH tmp1 AS ( select xxx ), tmp2 AS ( select xxxx ), tmp3 AS ( select xxxx ) SELECT * FROM tmp1 我们需要提取到with临时表部分,然后将其跟 "SELECT * FROM tmp1" 分离开来,这时候方法如下: public static void main(String[] args) { // 正则表达式 String formatPattern = "(with[\\s\\S]+as?\\s*\\([\\s\\S]+\\))\\s*select"; // 待匹配字符串 String sql = "WITH tmp1 AS ( select xxx ), " + "tmp2 AS ( select xxxx ), " + "tmp3 AS ( select xxxx ) " + "SELECT * FROM tmp1"; Pattern pattern = Pattern.compile(formatPattern); Matcher matcher = pattern.matcher(sql.toLowerCase()); int selectLen = "select".length(); if (matcher.find()) { String withFragment = matcher.group(); if (!StringUtils.isEmpty(withFragment)) { if (withFragment.length() > selectLen) { int lastSelectIndex = withFragment.length() - selectLen; sql = sql.substring(lastSelectIndex); withFragment = withFragment.substring(0, lastSelectIndex); } System.out.println("WITH部分:" + withFragment); System.out.println("其他部分:" + sql); } } }

输出为:



WITH部分:with tmp1 as ( select xxx ), tmp2 as ( select xxxx ), tmp3 as ( select xxxx )



其他部分:SELECT * FROM tmp1



以上,我们就可以很简单的把with部分和其他部分抽离出来了。






实际场景2 - PHP中将MySQL结果转为数组格式,格式如下:



将 var[^,]+ 替换为 => ''





如何运用正则表达式在SQL解析中实现复杂查询条件的匹配?






其他语法描述



①分组


((2[0-4]\d|25[0-5]|[01]?\d\d?)\.){3}(2[0-4]\d|25[0-5]|[01]?\d\d?)



匹配:IP



2[0-4]\d|25[0-5]|[01]?\d\d?



含义:() 括住的 是分组后内容





②后向引用



\b(\w+)\b\s+\1\b



匹配:go go



\1



含义:每个 括号 括起来的叫一个分组,分组写法 \1 \2 \3



\b(?<Word>\w+)\b\s*\k<Word>\b #?<Word>\w+ 定义,\k<Word>捕获





③位置指定(匹配指定位置前后)



\b\w+(?=ing\b) # 零宽先行断言



匹配:I'm singing while you're dancing.



(?=ing\b)





(?<=\bre)\w+\b



reading a book



(?<=\bre)





④负向位置指定



\b\w*q(?!u)\w*\b



匹配:Iraq fighting



(?!u)



含义:匹配后缀( 非 u)





(?<![a-z])\d{7}



匹配:_1234567



(?<![a-z])



含义:匹配前缀( 非 a-z)





⑤贪婪和懒惰



*?

重复任意次,但尽可能少重复

+?

重复1次或更多次,但尽可能少重复

??

重复0次或1次,但尽可能少重复

{n,m}?

重复n到m次,但尽可能少重复

{n,}?

重复n次以上,但尽可能少重复