前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >根据SQL提炼表信息

根据SQL提炼表信息

作者头像
jeanron100
发布2019-05-08 18:24:55
4750
发布2019-05-08 18:24:55
举报
文章被收录于专栏:杨建荣的学习笔记

这是学习笔记的第 1958 篇文章

在MySQL慢日志通过pt工具解析后有一个小问题,那就是我们很难得到一个完整的table列表,即假设一条SQL语句很长,那么我们其实想知道这条SQL相关的表是哪几个,如果能够很清晰的提炼出来,那么我们要做后续的分析就会锦上添花。

显然这个工作是有一些复杂度的,大体想了下,有以下的一些难点:

  1. select语句如果是多个表关联,那么这个提取工作就会增加解析的复杂度
  2. insert语句如果是insert xxx select xxx from的形式,那么得到的相关表应该是两个以上
  3. 如果是replace,load等语句,解析规则需要自己定制,目前没有通用的方法
  4. 如果语句含有注释,换行等符号,需要甄别和过滤

所以这一块算是有一些实现难度的功能,我们可以简化下思路,可以把SQL语句先做下格式化,把回车,换行,注释等都统一处理下。

这样在一个基本规范的前提下,我们把SQL语句切分成多份,然后按照语句的规则来做匹配,比如对于select语句,我们的提炼逻辑是找到from和join关键字的位置,进行table的信息提取。

关于语句的格式化部分,可以使用re来实现,主要是做正则表达式的相关逻辑检查。

然后指定一个字典结构,根据自定义的SQL匹配规则进行信息补充,这样对于insert语句,我们可以灵活的匹配insert select from的场景。

如果有些表名重复,为了去重排序,我们可以使用set的数据结构。

整体的代码实现如下:

import re

def extract_table_name_from_sql(sql_str):

# remove the /* */ comments

q = re.sub(r"/\*[^*]*\*+(?:[^*/][^*]*\*+)*/", "", sql_str)

# remove whole line -- and # comments

lines = [line for line in q.splitlines() if not re.match("^\s*(--|#)", line)]

# remove trailing -- and # comments

q = " ".join([re.split("--|#", line)[0] for line in lines])

# split on blanks, parens and semicolons

tokens = re.split(r"[\s)(;]+", q)

# scan the tokens with user-defined logic to get table info list

result = set()

if tokens.__len__()>0:

sql_type = tokens[0]

else:

sql_type = "dummy"

#print sql_type

sql_type_map = {}

sql_type_map["select"] =["from", "join"]

sql_type_map["update"] =["update","from"]

sql_type_map["insert"] =["into","from","join"]

sql_type_map["delete"] =["from"]

sql_type_map["load"] =["table"]

sql_type_map["replace"] =["into"]

sql_type_map["alter"] =["table"]

for idx, token in enumerate(tokens):

if token.lower() in sql_type_map[sql_type.lower()]:

result.add(tokens[idx+1])

return ",".join(str(i) for i in list(result))

打个比方,我们使用如下的测试SQL,需要解析table列表:

sql8="insert into test select xxxx from aa join b where aaaaa"

print(extract_table_name_from_sql(sql8))

得到的结果如下:

test,aa,b

对于select,load,update等语句,都可以灵活的调整字典里的配置来实现。

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-04-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 杨建荣的学习笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档