python中sql解析库sqlparse基本操作指南

 更新时间:2024年08月05日 09:32:25   作者:牧码文  
sqlparse是用于Python的非验证SQL解析器,它提供了对SQL语句的解析,拆分和格式化的支持,这篇文章主要给大家介绍了关于python中sql解析库sqlparse基本操作指南的相关资料,需要的朋友可以参考下

前言

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语句中的一个原子部分,如一个单词或者符号。它包含以下属性:

  • value: 该Token的实际文本内容,比如一个关键字像SELECT或一个标识符如表名。
  • token_type: 表示Token类型的枚举值,比如Keyword、Identifier、Punctuation等。
  • position 或 start_pos: 表示Token在原始SQL文本中的起始位置信息,有助于追踪Token的来源。
    相关Token子类和概念
  • sqlparse.sql.Identifier: 专门表示SQL中的标识符,如表名、列名等。这类Token可能会有额外的属性来表示是否为 quoted identifier(被引号包围的标识符)。
  • sqlparse.sql.Keyword: 表示SQL关键字,如SELECT, FROM, WHERE等。
  • sqlparse.sql.Punctuation: 表示SQL中的标点符号,如逗号,、分号;等。
  • sqlparse.sql.Comment: 用于表示SQL中的注释内容,可以是行内注释(-- …)或块注释(/* … */)。
  • sqlparse.sql.Comparison: 包含比较操作符(如=, !=, IN, BETWEEN等)以及它们两边的操作数,用于构建更复杂的表达式分析。
  • sqlparse.sql.Statement: 表示整个SQL语句,通常是由多个Token和其他Statement对象组成的树状结构,便于递归遍历整个SQL语句的结构。
    这里就需要引入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 ']

总结 

到此这篇关于python中sql解析库sqlparse基本操作的文章就介绍到这了,更多相关python sql解析库sqlparse内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • python-opencv实现视频指定帧数间隔图像的保存功能

    python-opencv实现视频指定帧数间隔图像的保存功能

    这篇文章主要介绍了python-opencv实现视频指定帧数间隔图像的保存的方法,本文通过示例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2021-04-04
  • Python3.5面向对象编程图文与实例详解

    Python3.5面向对象编程图文与实例详解

    这篇文章主要介绍了Python3.5面向对象编程,结合图文与实例形式详细分析了Python面向对象编程相关的概念、类定义、实例化、实例变量、类变量、析构函数等相关原理及使用技巧,需要的朋友可以参考下
    2019-04-04
  • Python实现图片格式转换

    Python实现图片格式转换

    经常会遇到图片格式需要转换的情况,这篇文章主要为大家详细介绍了Python实现图片格式转换,文中示例代码介绍的非常详细、实用,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2022-08-08
  • Python命令行参数解析工具 docopt 安装和应用过程详解

    Python命令行参数解析工具 docopt 安装和应用过程详解

    这篇文章主要介绍了Python命令行参数解析工具 docopt 安装和应用过程详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2019-09-09
  • Pandas分组聚合之使用自定义函数方法transform()、apply()

    Pandas分组聚合之使用自定义函数方法transform()、apply()

    Pandas具有很多强大的功能,transform就是其中之一,利用它可以高效地汇总数据且不改变数据行数,下面这篇文章主要给大家介绍了关于Pandas分组聚合之使用自定义函数方法transform()、apply()的相关资料,需要的朋友可以参考下
    2023-01-01
  • Python猜解网站数据库管理员密码的脚本

    Python猜解网站数据库管理员密码的脚本

    这篇文章主要和大家分享一个Python脚本,可以实现猜解网站数据库管理员的密码。文中的示例代码讲解详细,需要的小伙伴可以参考一下
    2022-02-02
  • python 在服务器上调用数据库特别慢的解决过程

    python 在服务器上调用数据库特别慢的解决过程

    这篇文章主要介绍了python 在服务器上调用数据库特别慢的解决过程,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • python统计列表中元素出现次数的三种方法

    python统计列表中元素出现次数的三种方法

    这篇文章主要介绍了python统计列表中元素出现次数的三种方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面跟着小编来一起学习学习吧
    2024-08-08
  • python读取excel文件的方法

    python读取excel文件的方法

    文章介绍了在Python中读取Excel文件的两种方法:使用pandas库和使用openpyxl库,pandas适合数据分析和处理,而openpyxl提供了更多的Excel文件操作功能,感兴趣的朋友跟随小编一起看看吧
    2024-11-11
  • Python实现xml格式转txt格式的示例代码

    Python实现xml格式转txt格式的示例代码

    VOC 的标注是xml格式的,而YOLO是.txt格式,所以要实现VOC数据集转YOLO数据集,只能利用代码实现。所以本文为大家介绍了Python中xml转txt的示例代码,需要的可以参考一下
    2022-03-03

最新评论