2026/4/6 4:06:03
网站建设
项目流程
win7用iis搭建网站,聚名网域名怎么过户给公司,专业手机网站建设公司排名,在电脑上怎么卸载wordpress内容目录 一、基本方法: 1.parse(sql)2.format(sql)3.split()4.parsestream() 二、Token三、其他类型四、案例: 提取所有查询的字段和表名 sqlparse 是一个 Python 库#xff0c;是一个用于 Python 的非验证 SQL 解析器, 用于解析 SQL 语句并提供一个简单的 API 来访问解析后…内容目录一、基本方法: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, encodingNone): 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, encodingNone, **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 语句字符串。reindentTrue: 自动重新缩进 SQL 语句使代码块对齐。keyword_case‘upper’: 将 SQL 关键字转换为大写。可选值有’lower’、‘upper’ 或 ‘capitalize’。其他可选参数还包括 indent_width用于设置缩进的空格数默认为 2、wrap_after设置换行的字符数限制等以进一步定制输出样式。import sqlparsesql “”“select * from tbl where id 10;”“”format sqlparse.format(sql, reindentTrue, keyword_case‘upper’)print(format)SELECT *FROM tblWHERE id 10;3.split()按照符号分割sql语句, 返回一个sql列表源码:def split(sql, encodingNone): 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, encodingNone): 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, encodingutf-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 valuesqlparse.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 doesnt 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空白字符如空格、制表符、换行符等 KeywordSQL 关键字如 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 ]