如何用正则表达式统计列表中各类SQL语句的数量?
解决SQL语句类型统计的正则方案
如果你用简单的前缀匹配(比如^SELECT)会遇到问题,比如关键字前有空格、大小写不统一、存在注释干扰等,下面是几个更健壮的正则实现思路:
1. 基础增强版(处理空格、大小写、整词匹配)
这个方案解决最常见的问题:语句前的空白字符、SQL关键字的大小写混用,以及避免匹配包含关键字的其他词(比如SELECT不会匹配SELECTION)。
正则表达式(需启用多行模式和不区分大小写模式):
^\s*(SELECT|INSERT|UPDATE|DELETE|CREATE|ALTER|DROP|MERGE)\b
^\s*: 匹配行首的任意空白字符(空格、制表符)(SELECT|INSERT|...): 枚举需要统计的SQL语句类型\b: 单词边界,确保匹配的是完整的关键字,而非其他词的一部分
使用示例(Python):
import re sql_text = """ SELECT * FROM TEST_TABLE INSERT INTO users VALUES (1, 'Alice') -- This is a comment UPDATE users SET name = 'Bob' WHERE id = 1 select * FROM orders """ pattern = re.compile(r'^\s*(SELECT|INSERT|UPDATE|DELETE)\b', re.MULTILINE | re.IGNORECASE) matches = pattern.findall(sql_text) # 统计数量 counts = {} for match in matches: keyword = match.upper() counts[keyword] = counts.get(keyword, 0) + 1 for keyword, num in counts.items(): print(f"{keyword} {num}")
输出:
SELECT 2 INSERT 1 UPDATE 1
2. 处理单行注释干扰
如果你的SQL里有--开头的单行注释,上面的正则会漏掉被注释行后面的语句吗?不,多行模式下^是行首,但如果注释和语句在同一行呢?比如-- TODO: SELECT * FROM table,这时候我们需要排除这种被注释的关键字。
改进正则(同样启用多行和不区分大小写):
^\s*(?:--.*?)?\s*(SELECT|INSERT|UPDATE|DELETE)\b
(?:--.*?)?: 可选的单行注释部分,?:表示非捕获组,.*?匹配注释内容直到行内的下一个有效字符(或者行尾)
但注意:如果注释和语句在同一行(比如SELECT * FROM -- test table),这个正则依然能正确匹配SELECT,因为它只跳过行首的注释。
3. 处理块注释(/* ... */)
块注释更复杂,尤其是跨多行的情况。正则可以处理非嵌套的块注释(大多数SQL dialect不支持嵌套块注释)。
思路是先移除所有块注释,再用基础正则统计:
正则移除块注释(需启用** DOTALL 模式**,让.匹配换行):
/\*.*?\*/
示例(Python):
# 先移除块注释 clean_sql = re.sub(r'/\*.*?\*/', '', sql_text, flags=re.DOTALL) # 再用基础正则统计 matches = pattern.findall(clean_sql)
这样就能排除掉/* SELECT * FROM table */这种被注释的关键字。
注意事项
- 嵌套块注释:正则无法可靠处理嵌套的
/* ... /* ... */ ... */,如果你的SQL有这种情况,可能需要用专门的SQL解析库(比如Python的sqlparse)来替代正则。 - 复杂语句:比如
WITH ... SELECT ...,这个正则依然能匹配到SELECT,因为我们只关心语句的起始关键字。 - 语句跨行:如果SQL语句被拆分成多行(比如
SELECT\n* FROM table),基础正则依然能匹配行首的SELECT,没问题。
内容的提问来源于stack exchange,提问作者thejoker34
相关产品推荐
相关产品推荐

