如何利用python来提取SQL语句中的表名称

news2024/9/21 4:20:52

1.介绍

在某些场景下,我们可能需要从一个复杂的SQL语句中提取对应的表名称,在这样的场景下,我们如果在python中处理的话,就需要用到SQLparse这个库。
SQLparse 是一个用于解析 SQL 查询语句的 Python 库。它可以将复杂的 SQL 查询转换为易于分析的结构,并提供了许多功能来检索、修改和分析 SQL 查询中的元素。其中一个常见的用例是从查询中提取表名称。

2.安装 SQLparse

首先,确保您已经安装了 SQLparse。您可以使用 pip 进行安装:

pip install sqlparse

3.解析 SQL 查询语句

使用 SQLparse 解析 SQL 查询语句非常简单。只需导入库并将查询语句作为字符串传递给 sqlparse.parse() 函数。

4.提取表名称

提取表名称通常涉及到遍历解析后的 SQL 结构以查找关键元素,这些元素通常表示表名称。SQLparse 使用了一种抽象语法树(AST)的结构,可以轻松访问查询中的各个部分。

示例代码
下面是一个示例代码,演示如何使用 SQLparse 从简单的SQL 查询语句中得到表名称:

import sqlparse
# 定义一个 SQL 查询语句
sql_query = "SELECT * FROM customers WHERE age > 30;"
# 解析 SQL 查询语句
parsed_query = sqlparse.parse(sql_query)
# 遍历解析出表名
table_names=[]
for stmt in parsed_query:
    for token in stmt.tokens:
        if isinstance(token, sqlparse.sql.Identifier) :
            table_name= token.get_real_name()
            table_names.append(table_name)
print(table_names)  

代码运行后,结果如下:
1

在上述代码中,我们首先定义了一个 SQL 查询语句。然后,我们使用 SQLparse 解析查询语句,将其转换为 AST 结构。接下来,我们遍历 AST 结构以查找关键元素,例如表名称。但是敏感和聪明的你,会发现用上述代码在实际场景中时会出现各种各样的问题。

5.实际场景中的问题

5.1 无法处理嵌套类型的语句

如在处理下面这个SQL语句时,无法提取嵌套在里面的表名称

    SELECT o.id, o.name FROM orders o
    LEFT JOIN products p ON o.product_code = p.product_code
    WHERE o.customer_id IN (
        SELECT id FROM customers 
        WHERE country = 'USA'
    )
    OR p.category = 'Electronics'

简单的嵌套,无法识别:
2

5.2 无法处理重命名表的语句

如下面的SQL语句,会出现提取错误的情况:

with co as 
(SELECT o.id, o.name FROM orders o
    LEFT JOIN products p ON o.product_code = p.product_code
    WHERE o.customer_id IN (
        SELECT id FROM customers 
        WHERE country = 'USA'
    )
    OR p.category = 'Electronics')
select * from co

提取结果如下:
3

5.3 多个表名重复时的去重问题

在处理基础的SQL语句时,会出现多个相同的表

    SELECT o.id, o.name FROM orders o
    LEFT JOIN orders o2 on o.id = o2.pre_id

处理后,截图如下:
4

5.4 其他问题

有一些场景下,还会提取出字段信息夹杂其中的情况,或者有一些存在表空间的情况会进行重命名,等等,听到这里,你是不是觉得处理起来令人头大?别慌,接着往下看。

6.终极解决方案

6.1 解决思路

经过本人的一番思考后,采用sqlparse模块和re模块相结合后,惊喜的发现,能够灵活的从绝大部分的sql语句中正确地提取出表名称来。
解决思路如下:

  • 1.先将sql语句进行规范
  • 2.获取left和join关键字后面的表名
  • 3.对表名进行各种处理
  • 4.去重后输出结果

6.2 实际代码

import sqlparse
import re


def format_sql(sql_content):
    '''将sql语句进行规范化,并去除sql中的注释,输入和输出均为字符串'''
    parse_str=sqlparse.format(sql_content,reindent=True,strip_comments=True)
    return parse_str

def extract_table_names(sql_query):
    '''从sql中提取对应的表名称,输出为列表'''
    table_names = set()
    # 解析SQL语句
    parsed = sqlparse.parse(sql_query)
    # 正则表达式模式,用于匹配表名
    table_name_pattern = r'\bFROM\s+([^\s\(\)\,]+)|\bJOIN\s+([^\s\(\)\,]+)'
    # with 子句判断
    with_pattern = r'with\s+(\w+)\s+as'
    remove_with_name=[]
    
    # 遍历解析后的语句块
    for statement in parsed:
        # 转换为字符串
        statement_str =  str(statement).lower()
        
        #将字符串中的特殊语法置空
        statement_str = re.sub('(substring|extract)\s*\(((.|\s)*?)\)','',statement_str)
        
        # 查找匹配的表名
        matches = re.findall(table_name_pattern, statement_str, re.IGNORECASE)
        
        for match in matches:
            # 提取非空的表名部分
            for name in match:
                #if name and name not in not_contain_list:
                if name :
                    # 对于可能包含命名空间的情况,只保留最后一部分作为表名
                    table_name = name.split('.')[-1]
                    #去除表名中的特殊符号
                    table_name = re.sub('("|`|\'|;)','',table_name)
                    table_names.add(table_name)
        #处理特殊的with语句
        if 'with' in statement_str:
            match = re.search(with_pattern, statement_str)
            if match:
                result = match.group(1)
                remove_with_name.append(result)
    table_list = list(table_names)
    #移除多余的表名
    if remove_with_name:
        table_list =list(set(table_list)-set(remove_with_name))
    return table_list
sql_query='''with co as 
(SELECT o.id, o.name FROM orders o
    LEFT JOIN products p ON o.product_code = p.product_code
    WHERE o.customer_id IN (
        SELECT id FROM customers 
        WHERE country = 'USA'
    )
    OR p.category = 'Electronics')
select * from co'''
parse_str=format_sql(sql_query)
table_names = extract_table_names(parse_str)
# 打印提取的表名
print(table_names)

通过运行上述的代码,成功提取到多有表名称
6

7 后记

以上就是如何从一个复杂的SQL语句中来提取表名的例子,欢迎各位踊跃尝试,勇于纠错,一起完善代码,让更多的人收益,一起加油~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/987494.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

解决js计算小数不准的问题

1.使用计算函数 function accAdd(arg1, arg2) {var r1, r2, m;try { r1 arg1.toString().split(".")[1].length } catch (e) { r1 0 };try { r2 arg2.toString().split(".")[1].length } catch (e) { r2 0 };m Math.pow(10, Math.max(r1, r2));retur…

2023年9月北京/广州/深圳DAMA-CDGP数据治理专家认证报名

DAMA认证为数据管理专业人士提供职业目标晋升规划,彰显了职业发展里程碑及发展阶梯定义,帮助数据管理从业人士获得企业数字化转型战略下的必备职业能力,促进开展工作实践应用及实际问题解决,形成企业所需的新数字经济下的核心职业…

el-form表单中不同数据类型对应的时间格式化和校验规则

1. 在表单中, 当选择不同的数据类型时, 需要在下面选择时间时和数据类型对应上, 通过监听数据类型的变化, 给时间做格式化, 2. 但是当不按顺序选择数据类型后, 再选时间可能会报错, 所以需要在dom更新后, 再清空表单. 3. 校验规则, 结束时间需要大于开始时间, 但是不能选当前的…

报错ssh: Could not resolve hostname

…按照网上好多教程试了一下: 新建密钥,添加到gitee,重新测试。修改host,加入gitee的ip地址到里面去。修改.gifconfig配置文件,配置成ssh的仓库链接。 这上面的方法都不行,后面发现一篇文章:SS…

Spring 6.X IoC 容器

目录 一、Spring IoC 容器和 Bean 简介1.1、容器概述1.3、使用 一、Spring IoC 容器和 Bean 简介 下面主要介绍 Spring 框架对控制反转 (IoC) 原理的实现 首先要说明的是:IoC 也称为依赖注入,这是一个过程。 其次依赖项的定义:对象仅通过构造…

RSS订阅无需代码连接Outlook的方法

RSS订阅用户使用场景: 一家专门做书籍测评的企业,其日常工作中需要收集豆瓣上最受欢迎的书籍进行测评。为了确保测评的准确性和客观性,团队成员需要定期在Outlook上创建会议讨论新书,从不同角度对书籍进行深入剖析。然而&#xff…

Ansys Zemax | 如何将光线追迹结果导出为IES格式

照明系统设计者通常需要向客户提供IES格式的数据。照明工程学会 (Illuminating Engineering Society,IES) 文件格式便于传输辉度数据,该格式得到了制造商和设计师的广泛认可。本文描述了如何生成IES文件并验证结果。(联系我们获取文章附件&am…

24张架构图讲透数据治理核心内容

加ghz“大数据食铁兽”,了解更多大数据资讯! 一、数据治理的框架和核心内容 不同的利益相关者群体对数据治理的关注点不一样,因此各自的视图也不一样。其中管理者视图可以概括为“五域模型”,分别是“管控域”、“过程域”、“治…

虹科干货 | 码住!虹科工业树莓派应用小tips!

文章来源:虹科工业物联网 点此阅读原文,获取更多干货资料 虹科工业树莓派应用小tips 在应用虹科工业树莓派进行项目开发的过程中,我们会应用到各种功能,部分功能看似不起眼,但是在实际应用开发过程中却非常重要。接…

[C题]2023 年全国大学生数学建模比赛思路、代码更新中.....

💥1 概述 在生鲜商超中,一般蔬菜类商品的保鲜期都比较短,且品相随销售时间的增加而变差,大部分品种如当日未售出,隔日就无法再售。因此,商超通常会根据各商品的历史销售和需求情况每天进行补货。由于商超销…

输送机安装的注意事项

输送机也称输送线,是指在自动化生产过程中起到运输和过渡作用的线体,一般常用的输送机有:滚筒线、皮带线、链条线、链板线等。但无论是哪种输送机,都会涉及到安装的问题,今天我们就从专业的角度来和您分享一下输送机安…

软件供应链安全在金融机构中的最佳实践 | 金融系统安全实战专题交流会圆满成功

9月6日,由广东省粤港澳合作促进会金融专业委员会和粤港澳大湾区金融创新研究院联合举办,开源网安协办的“2023年金融系统安全运营与实战专题交流会”圆满落幕。本次会议紧紧围绕加强安全运营中心建设、应对风险、加强数据安全治理,保障数据安…

字节一面:css选择器有哪些?优先级?哪些属性可以继承?

前言 最近博主在字节面试中遇到这样一个面试题,这个问题也是前端面试的高频问题,作为一名前端开发工程师,css是我们的必备技能,熟悉css选择器以及继承是我们写好css的关键,博主在这给大家细细道来。 🚀 作者…

PHP实现微信小程序状态检测(违规、暂停服务、维护中、正在修复)

实现原理 进入那些状态不正常的小程序会被重定向至一个Url&#xff0c;使用抓包软件抓取这个Url&#xff0c;剔除不必要参数&#xff0c;使用cURl函数请求网页获得HTML内容&#xff0c;根据内容解析出当前APPID的小程序的状态。 代码 <?php// 编码header(Content-type:ap…

Flink--2、Flink部署(Yarn集群搭建下的会话模式部署、单作业模式部署、应用模式部署)

星光下的赶路人star的个人主页 你必须赢过&#xff0c;才可以说不在乎输赢 文章目录 1、Flink部署1.1 集群角色1.2 Flink集群搭建1.2.1 集群启动1.2.2 向集群提交作业 1.3 部署模式1.3.1 会话模式&#xff08;Session Mode&#xff09;1.3.2 单作业模式&#xff08;Per-Job Mod…

业绩大变脸!上半年净亏1.1亿元,经纬恒润怎么了?

2023年上半年&#xff0c;中国汽车市场需求逐步恢复&#xff0c;智能电动汽车市场则呈现出了“高歌猛进”的现象&#xff0c;但经纬恒润却面临了业绩大变脸。 经纬恒润&#xff08;688326.SH&#xff09;成立于2003年&#xff0c;基于Mobileye方案顺利进入了ADAS前装量产市场&…

软件设计师(十二)多媒体基础

一、多媒体技术的基本概念 1、音频相关概念 PC处理的音频信号主要是人耳能听得到的音频信号 (audio) &#xff0c;它的频率范围是20Hz ~ 20kHz。 可听声包括&#xff1a;话音 (也称语言)&#xff1a;人的说话声&#xff0c;频率范围通常为300 ~ 3400Hz。 音乐&#xff1a;由乐…

电脑文件误删除如何恢复?这4个常用方法记好了!

“我怎么又误删了重要的文件啊&#xff01;这种情况已经不是第一次出现了&#xff0c;真的很让人烦恼&#xff01;大家在误删了重要的文件之后都是怎么恢复的呀&#xff1f;有什么好用的方法推荐吗&#xff1f;” 在日常使用电脑的过程中&#xff0c;误删文件的事大家可能都会遇…

鸿蒙系列-如何使用DevEco分析app的性能

如何使用DevEco分析app的性能 性能优化、启动优化、内存优化、FPS监测、性能分析&#x1f9d0; 在鸿蒙OpenHarmony开发过程中&#xff0c;开发者开发的代码&#xff08;Stage 模型&#xff09;通常以调用 ArkUI 框架的代码为主&#xff0c;主要优化的代码部分也在其中&#x…

Java“牵手”易贝商品列表数据,关键词搜索易贝商品数据接口,易贝API申请指南

ebay商城是一个网上购物平台&#xff0c;售卖各类商品&#xff0c;包括服装、鞋类、家居用品、美妆产品、电子产品等。要获取ebay商品列表和商品详情页面数据&#xff0c;您可以通过开放平台的接口或者直接访问ebay商城的网页来获取商品详情信息。以下是两种常用方法的介绍&…