python的sql解析库-sqlparse

内容目录
      • 一、基本方法:
        • 1.parse(sql)
        • 2.format(sql)
        • 3.split()
        • 4.parsestream()
      • 二、Token
      • 三、其他类型
      • 四、案例: 提取所有查询的字段和表名

sqlparse 是一个 Python 库,是一个用于 Python 的非验证 SQL 解析器, 用于解析 SQL 语句并提供一个简单的 API 来访问解析后的 SQL 结构。可以帮助解析复杂的 SQL 查询,提取信息,或者对 SQL 语句进行一些基本的分析和操作。

一、基本方法:

sqlparse的__init__方法中提供了四个基础方法

1.parse(sql)

用于将一个或多个 SQL 语句的字符串解析成 Python 对象,这些对象构成了一个抽象语法树(AST)
源码

def parse(sql, encoding=None): """Parse sql and return a list of statements. :param sql: A string containing one or more SQL statements. :param encoding: The encoding of the statement (optional). :returns: A tuple of :class:`~sqlparse.sql.Statement` instances. """ return tuple(parsestream(sql, encoding))

按照符号分割sql后返回一个元组, 可以递归获取所有的值

import sqlparse SQL = """CREATE TABLE foo ( id integer primary key comment 'id_comm', title varchar(200) not null comment 'id_comm', description text comment 'id_comm');""" parsed = sqlparse.parse(SQL)[0] print(parsed)
2.format(sql)

格式化代码, 返回格式化后的代码字符串
源码:

def format(sql, encoding=None, **options): """Format *sql* according to *options*. Available options are documented in :ref:`formatting`. In addition to the formatting options this function accepts the keyword "encoding" which determines the encoding of the statement. :returns: The formatted SQL statement as string. """

参数说明:

  • sql: 需要格式化的 SQL 语句字符串。

  • reindent=True: 自动重新缩进 SQL 语句,使代码块对齐。

  • keyword_case=‘upper’: 将 SQL 关键字转换为大写。可选值有’lower’、‘upper’ 或 ‘capitalize’。

  • 其他可选参数还包括 indent_width(用于设置缩进的空格数,默认为 2)、wrap_after(设置换行的字符数限制)等,以进一步定制输出样式。

    import sqlparse

    sql = “”“select * from tbl where id > 10;”“”

    format = sqlparse.format(sql, reindent=True, keyword_case=‘upper’)

    print(format)

    SELECT *

    FROM tbl

    WHERE id > 10;

3.split()

按照符号分割sql语句, 返回一个sql列表
源码:

def split(sql, encoding=None): """Split *sql* into single statements. :param sql: A string containing one or more SQL statements. :param encoding: The encoding of the statement (optional). :returns: A list of strings. """ import sqlparse sql = """select * from tbl where id > 10;select * from tbl where id > 20;""" split = sqlparse.split(sql) print(split) # ['select * from tbl where id > 10;', 'select * from tbl where id > 20;']
4.parsestream()

类似parse方法, 流式解析sql, 它的设计初衷是为了处理从流式输入(如文件、网络连接或任何可迭代的对象)读取的 SQL 代码,而不是一次性加载整个 SQL 字符串到内存中。这样,在处理大型 SQL 文件或连续的数据流时,可以更有效地管理内存。
源码:

def parsestream(stream, encoding=None): """Parses sql statements from file-like object. :param stream: A file-like object. :param encoding: The encoding of the stream contents (optional). :returns: A generator of :class:`~sqlparse.sql.Statement` instances. """ with open('../static/pre_sql.sql', 'r', encoding='utf-8') as file: for statement in sqlparse.parse(file): print(statement)
二、Token

源码:

class Token: """Base class for all other classes in this module. It represents a single token and has two instance attributes: ``value`` is the unchanged value of the token and ``ttype`` is the type of the token. """ def __init__(self, ttype, value): value = str(value) self.value = value self.ttype = ttype self.parent = None self.is_group = False self.is_keyword = ttype in T.Keyword self.is_whitespace = self.ttype in T.Whitespace self.normalized = value.upper() if self.is_keyword else value

sqlparse.sql.Token: 这是最基本的Token类,表示SQL语句中的一个原子部分,如一个单词或者符号。它包含以下属性:

sql -> 语法分析器(Lexer) -> Token流 -> 语法分析器(Parse) -> 抽象语法树(AST) -> 树结构(Tree Parse)

每个解析结果都会附带一个tokens 的属性,它是一个生成器,用于迭代解析后的Token序列, 包含了一些类型信息, 其中的类型信息有:

# Special token types Text = Token.Text Whitespace = Text.Whitespace Newline = Whitespace.Newline Error = Token.Error # Text that doesn't belong to this lexer (e.g. HTML in PHP) Other = Token.Other # Common token types for source code Keyword = Token.Keyword Name = Token.Name Literal = Token.Literal String = Literal.String Number = Literal.Number Punctuation = Token.Punctuation Operator = Token.Operator Comparison = Operator.Comparison Wildcard = Token.Wildcard Comment = Token.Comment Assignment = Token.Assignment # Generic types for non-source code Generic = Token.Generic Command = Generic.Command # String and some others are not direct children of Token. # alias them: Token.Token = Token Token.String = String Token.Number = Number # SQL specific tokens DML = Keyword.DML DDL = Keyword.DDL CTE = Keyword.CTE Text: 基础文本类型,通常用于表示SQL语句中的普通文本部分。 Whitespace: 空白字符,包括空格、制表符等,用于分隔SQL语句的不同部分。 Newline: 特指换行符,用于标识新的一行开始。 Error: 表示解析过程中遇到的无法识别或错误的文本。 Other: 表示不属于当前解析器(如SQL解析器)预期的文本,例如在嵌入式SQL中可能遇到的其他语言(如HTML在PHP中的情况)。 Keyword: SQL关键字,如 SELECT, FROM, WHERE 等。 DML: 数据操作语言(Data Manipulation Language)关键字,如 INSERT, UPDATE, DELETE, SELECT。 DDL: 数据定义语言(Data Definition Language)关键字,如 CREATE, ALTER, DROP。 CTE: 公共表达式(Common Table Expression)关键字,如 WITH。 Name: 数据库对象名称,如表名、列名等。 Literal: 字面量值,直接写在SQL中的数据值。 String: 字符串字面量,如 'example string'。 Number: 数字字面量,如 42, 3.14。 Punctuation: 标点符号,如逗号、括号等,用于分隔或包围SQL的各个部分。 Operator: 操作符,如 +, -, *, /, = 等。 Comparison: 比较操作符,如 =, !=, <, > 等。 Wildcard: 通配符,如 % 在某些SQL上下文中的使用。 Comment: 注释,SQL中的单行或多行注释。 Assignment: 赋值操作符,如 := 在某些SQL方言中用于赋值。 Generic: 通用类型,适用于非特定源代码的分隔。 Command: 命令,可能特指一些SQL命令或交互式shell命令。 Whitespace:空白字符(如空格、制表符、换行符等) Keyword:SQL 关键字(如 SELECT、FROM、WHERE 等) Name:标识符(如表名、列名等) String.Single:单引号字符串字面量 String.Double:双引号字符串字面量(在某些 SQL 方言中用于标识符) String.Backtick:反引号字符串字面量(如 MySQL 中的表名和列名) Identifier: 表示SQL中的标识符,包括但不限于表名、列名、数据库名等。 Compound: 复合Token,可能包含多个子Token,用于更复杂的结构,如 Case 语句、 When 条件等。 Number.Integer:整数 Number.Float:浮点数 Number.Hex:十六进制数 Operator:操作符(如 =、<>、+、- 等) Punctuation:标点符号(如逗号、分号、括号等) Comment.Single:单行注释 Comment.Multiline:多行注释 Wildcard:通配符(如 *) Function:函数名(如 COUNT()、MAX() 等) DML、DDL、DCL 等:表示数据操作语言、数据定义语言、数据控制语言等的高级分类
三、其他类型

有些属于token的属性
但有些不属于token, 比如Where、IdentifierList、Identifier、Parenthesis、Comment等

sql = 'select 1 as id, name, case when name = "" then 3 else 4 end as score from tbl where id > 10 limit 100' stmts = sqlparse.parse(sql)[0].tokens for stmt in stmts: print(f"{type(stmt)}::{stmt.ttype}::",stmt) # <class 'sqlparse.sql.Token'>::Token.Keyword.DML:: select # <class 'sqlparse.sql.Token'>::Token.Text.Whitespace:: # <class 'sqlparse.sql.IdentifierList'>::None:: 1 as id, name, case when name = "" then 3 else 4 end as score # <class 'sqlparse.sql.Token'>::Token.Text.Whitespace:: # <class 'sqlparse.sql.Token'>::Token.Keyword:: from # <class 'sqlparse.sql.Token'>::Token.Text.Whitespace:: # <class 'sqlparse.sql.Identifier'>::None:: tbl # <class 'sqlparse.sql.Token'>::Token.Text.Whitespace:: # <class 'sqlparse.sql.Where'>::None:: where id > 10 # <class 'sqlparse.sql.Token'>::Token.Keyword:: limit # <class 'sqlparse.sql.Token'>::Token.Text.Whitespace:: # <class 'sqlparse.sql.Token'>::Token.Literal.Number.Integer:: 100

当查询有多列或者有多表时, 会将其封装为IdentifierList, 单表时候会被封装为Identifier, 过滤条件被封装为Where, 括号会被封装为Parenthesis, 注释会被封装为Comment

四、案例: 提取所有查询的字段和表名
import sqlparse import re sql = 'insert into table inser_tbl partition (dt = dt) select 1 as id, name, case when (name = "" or name = "") then 3 else 4 end as score from tbl where id > 10 limit 100' stmts = sqlparse.parse(sql)[0].tokens cols = [] tbls = [] froms = [] wheres = [] last_key = '' for stmt in stmts: if stmt.value == 'insert' or stmt.value == 'select' or stmt.value == 'from': last_key = stmt.value # 剔除空格和换行 if stmt.ttype is sqlparse.tokens.Text.Whitespace: continue # 关键字 elif stmt.ttype is sqlparse.tokens.Keyword.DML: dml = stmt.value last_key = dml # 字段 elif isinstance(stmt, sqlparse.sql.IdentifierList): # 判断上一个是什么类型 if last_key == 'select': for identifier in stmt.get_identifiers(): col_name = identifier.value if re.search('as', col_name, re.I): col_name = re.search('as (.*)', col_name, re.I).group(1).strip() cols.append(col_name) elif last_key == 'from': for identifier in stmt.get_identifiers(): froms.append(identifier.value) else: for identifier in stmt.get_identifiers(): tbls.append(identifier.value) elif isinstance(stmt, sqlparse.sql.Identifier): if last_key == 'select': cols.append(stmt.value) elif last_key == 'from': froms.append(stmt.value) else: tbls.append(stmt.value) elif isinstance(stmt, sqlparse.sql.Where): wheres.append(stmt.value) # 表名 print("cols:", cols) print("tbls:", tbls) print("froms:", froms) print("wheres:", wheres) # cols: ['id', 'name', 'score'] # tbls: ['inser_tbl'] # froms: ['tbl'] # wheres: ['where id > 10 ']

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

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

相关文章

数字频率计共阴极数码管驱动电路实战

数码管驱动实战&#xff1a;如何用51单片机点亮4位频率计显示屏&#xff1f;你有没有遇到过这样的问题&#xff1a;想做个数字频率计&#xff0c;测出的频率值却没法“亮”出来&#xff1f;或者好不容易接上数码管&#xff0c;结果显示闪烁、重影&#xff0c;甚至MCU IO口直接拉…

Java Web 教学资源库系统源码-SpringBoot2+Vue3+MyBatis-Plus+MySQL8.0【含文档】

&#x1f4a1;实话实说&#xff1a;有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着信息技术的快速发展&#xff0c;教育领域对数字化教学资源的需求日益增长。传统的教学资源管理方式存在资源分散、检索效率低、共享困难等问题…

Python爬虫完整代码拿走不谢

对于新手做Python爬虫来说是有点难处的&#xff0c;前期练习的时候可以直接套用模板&#xff0c;这样省时省力还很方便。 使用Python爬取某网站的相关数据&#xff0c;并保存到同目录下Excel。 直接上代码&#xff1a; import re import urllib.error import urllib.requestimp…

系统管理工具,多功能隐私清理文件粉碎工具

软件介绍 今天给大伙儿安利个全能的系统管理工具&#xff0c;它叫 Windows超级管理器。功能那叫一个全乎&#xff0c;系统检测、文件清理、隐私保护、磁盘管理、文件粉碎这些实用活儿它都能干&#xff0c;堪称系统管家&#xff01; 绿色单文件版&#xff1a;小巧便携的系统管…

SpringBoot+Vue 智能推荐卫生健康系统平台完整项目源码+SQL脚本+接口文档【Java Web毕设】

&#x1f4a1;实话实说&#xff1a;CSDN上做毕设辅导的都是专业技术服务&#xff0c;大家都要生活&#xff0c;这个很正常。我和其他人不同的是&#xff0c;我有自己的项目库存&#xff0c;不需要找别人拿货再加价。我就是个在校研究生&#xff0c;兼职赚点饭钱贴补生活费&…

【踩坑记】WSL1 下 Docker 报错 iptables: No chain/target/match by that name 排查实录

这是一篇为你整理的“踩坑记”&#xff0c;还原了从报错、排查到发现核心原因并解决的全过程。【踩坑记】WSL1 下 Docker 报错 iptables: No chain/target/match by that name 排查实录1. 背景与环境今天在 WSL (Ubuntu 24.04) 环境下部署 Dify 项目&#xff0c;执行启动命令时…

autosar软件开发中诊断协议栈配置实践案例

AUTOSAR诊断协议栈配置实战&#xff1a;从UDS服务到DTC管理的全链路解析在一辆现代智能汽车中&#xff0c;当你用诊断仪读取一个故障码、刷新ECU程序&#xff0c;或是远程获取车辆实时数据时——背后支撑这一切的&#xff0c;正是AUTOSAR架构中的诊断通信协议栈。它不仅是连接整…

MPC5634 Bootloader

MPC5634 Bootloader嵌入式工程师最怕遇到设备变砖&#xff0c;而好的Bootloader设计就是咱们的救命稻草。今天咱们来盘一盘飞思卡尔MPC5634这颗工业级控制器的Bootloader实现&#xff0c;直接上干货不啰嗦。先说启动流程&#xff0c;这货上电先执行0x00地址的启动代码。来看关键…

无线网络仿真:5G网络仿真_(3).5G关键技术和性能指标

5G关键技术和性能指标 1. 大规模MIMO技术 1.1 原理 大规模MIMO&#xff08;Multiple-Input Multiple-Output&#xff09;技术是5G网络中的一项重要技术&#xff0c;通过在基站和用户设备上部署大量的天线&#xff0c;可以显著提升无线通信系统的容量和频谱效率。大规模MIMO技术…

洗衣店订单管理系统信息管理系统源码-SpringBoot后端+Vue前端+MySQL【可直接运行】

&#x1f4a1;实话实说&#xff1a;有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着现代生活节奏的加快&#xff0c;洗衣服务行业逐渐成为城市居民日常生活的重要组成部分。传统的洗衣店管理方式依赖手工记录订单信息&#xff0…

RabbitMQ 集群部署方案

RabbitMQ 一、安装 RabbitMQ 二、更改配置文件 三、配置集群 四、测试 环境准备&#xff1a;三台服务器&#xff0c;系统是 CentOS7 IP地址分别是&#xff1a; rabbitmq1&#xff1a;192.168.152.71rabbitmq2&#xff1a;192.168.152.72rabbitmq3&#xff1a;192.168.152.…

WSL Ubuntu 安装 Docker 操作指南

环境信息 操作系统&#xff1a;Windows 10/11WSL版本&#xff1a;WSL 1 或 WSL 2Linux发行版&#xff1a;Ubuntu 24.04 LTSDocker版本&#xff1a;29.1.4 前提条件 已安装WSL已安装Ubuntu 24.04发行版具有sudo权限的用户账户 安装步骤 1. 检查WSL环境状态 首先检查WSL的运…

Python高级之操作Mysql

Python高级 文章目录 Python高级 python操作数据库mysql-connector demo_mysql_test.py: pyMysql python操作数据库mysql-connector 本章节为大家介绍使用 mysql-connector 来连接使用 MySQL&#xff0c; mysql-connector 是 MySQL 官方提供的驱动器。 可以使用 pip 命令…

35 岁职场危机?网络安全这行为啥越老越吃香?

前几天我表弟小王来找我喝茶&#xff0c;聊着聊着突然问我&#xff1a;“老曹&#xff0c;你说我要不要转行做网络安全啊&#xff1f; 听说这行业挺赚钱的。 “我一听就笑了&#xff0c;这不正好最近我刚研究过这个行业吗&#xff1f; 我跟他说&#xff0c;别看现在各行各业…

cruise仿真模型,四轮驱动。 轮毂电机,轮边电机驱动cruise动力性经济性仿真模型,ba...

cruise仿真模型&#xff0c;四轮驱动。 轮毂电机&#xff0c;轮边电机驱动cruise动力性经济性仿真模型&#xff0c;base模型&#xff0c;适用轮边电机驱动及轮毂电机驱动。 可进行动力性经济性仿真分析&#xff0c;控制策略包含扭矩控制及能量回收控制使用c-code编写&#xff0…

SpringBoot+Vue 课程答疑系统管理平台源码【适合毕设/课设/学习】Java+MySQL

&#x1f4a1;实话实说&#xff1a; 有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。 摘要 随着信息技术的快速发展&#xff0c;教育信息化已成为现代教育的重要组成部分。传统的课程答疑方式通常依赖于面对面交流或简单的在线工具&…

从零实现framebuffer显示:裸机环境下简单图形输出教程

点亮第一行像素&#xff1a;在裸机中实现Framebuffer图形输出的硬核实践你有没有试过&#xff0c;在一块全新的开发板上电后&#xff0c;除了串口打印出几行冰冷的“Hello World”&#xff0c;屏幕却始终漆黑一片&#xff1f;这种“看得见摸不着”的调试困境&#xff0c;正是许…

前后端分离BB平台系统|SpringBoot+Vue+MyBatis+MySQL完整源码+部署教程

&#x1f4a1;实话实说&#xff1a;有自己的项目库存&#xff0c;不需要找别人拿货再加价&#xff0c;所以能给到超低价格。摘要 随着互联网技术的快速发展&#xff0c;传统单体架构的Web应用逐渐暴露出开发效率低、维护成本高、扩展性差等问题。前后端分离架构因其模块化、高内…

安全副业指南:漏洞挖掘 / 技术博客 / 竞赛奖金实战,哪个方向更适合你?

安全副业指南&#xff1a;漏洞挖掘 / 技术博客 / 竞赛奖金实战 很多安全从业者和学生都想通过技能赚 “外快”&#xff0c;却陷入 “想做漏洞挖掘怕没经验&#xff0c;想写博客怕没人看&#xff0c;想打竞赛怕拿不到奖” 的困境。其实安全副业的核心不是 “天赋”&#xff0c;而…

【教程4>第10章>第21节】基于FPGA的图像Laplace边缘提取算法开发——理论分析与matlab仿真

目录 1.软件版本 2.图像Laplace边缘提取算法理论概述 3.图像Laplace边缘提取的matlab仿真测试 欢迎订阅FPGA/MATLAB/Simulink系列教程 《★教程1:matlab入门100例》 《★教程2:fpga入门100例》 《★教程3:simulink入门60例》 《★教程4:FPGA/MATLAB/Simulink联合开发入门与进…