SQL解析工具JSQLParser
一、引言
JSQLParser(GitHub:https://github.com/JSQLParser/JSqlParser)是一个Java语言的SQL语句解析工具,功能十分强大,它可以将SQL语句解析成为Java类的层次结构,还支持改写SQL,常见的持久层框架MyBatis-Plus就采用它作为SQL解析工具来实现某些功能。
二、JSQLParser常见类
2.1 Class Diagram

2.2 Statement
可以理解为能够表示任意一种SQL语句的对象,Select、Update、Delete、Insert都是它的子类,例如以下用法:
Statement statement = JsqlParserGlobal.parse(sql);
if (statement instanceof Insert) {
this.processInsert((Insert) statement, index, sql, obj);
} else if (statement instanceof Select) {
this.processSelect((Select) statement, index, sql, obj);
} else if (statement instanceof Update) {
this.processUpdate((Update) statement, index, sql, obj);
} else if (statement instanceof Delete) {
this.processDelete((Delete) statement, index, sql, obj);
}
2.3 Expression
是JSqlParser库中的一个核心接口,是用于表示SQL语句中的各种表达式的基类接口,通过调用对象的.toString()方法,就能看到具体的语句结构。
例如:
- 基本值
LongValue(整数值)、StringValue(字符串值)、DoubleValue(浮点数值)等。
- 列引用
Column(表示列名,如column_name或table.column)。
- 运算符
Addition(+)、Subtraction(-)、Multiplication(*)、Division(/)等。
- 函数调用
Function(如COUNT(*)、SUBSTRING(str, 1, 2))。
- 条件表达式
EqualsTo(=)、NotEqualsTo(<>或!=)、GreaterThan(>)、LikeExpression(LIKE)等。
- 逻辑表达式(BinaryExpression)
AndExpression(AND)、OrExpression(OR)、NotExpression(NOT)。
- 子查询
SubSelect(如(SELECT ...))。
- Case 表达式
CaseExpression(CASE WHEN ... THEN ... END)。
- 其他复杂表达式
CastExpression(CAST(... AS ...))、IntervalExpression(时间间隔)等。
2.4 Select
用于表示查询SQL语句,有三个常见子类:PlainSelect,ParenthesedSelect,SetOperationList
2.5 Update
用于表示更新的SQL语句
获得对应表
Table table = update.getTable();
获得要更新的值
List<UpdateSet> sets = update.getUpdateSets();
获取where条件
Expression expression = update.getWhere()
2.6 Delete
用于表示删除的SQL语句
获得对应表
Table table = delete.getTable();
获取where条件
Expression expression = delete.getWhere()
2.7 Insert
用于表示添加SQL语句,有以下几种常见方法
获取添加的列
List<Column> columns = insert.getColumns();
获取添加的值
Values values = insert.getValues();
获取添加时冲突进行更新的结构
INSERT INTO ... VALUES ...ON DUPLICATE KEY UPDATE ...
List<UpdateSet> duplicateUpdateColumns = insert.getDuplicateUpdateSets();
insert select的结构,获取select
INSERT ... SELECT ...
Select select = insert.getSelect();
2.8 PlainSelect
用于表示最常规的那种查询结构,例如:
select...from...join...where...
获取select后面的结构
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
获取select语句的where结构
Expression where = plainSelect.getWhere();
获取查询的from后的结构(表,子查询等)
FromItem fromItem = plainSelect.getFromItem();
存在连接查询时,获取连接查询(left/right/inner)join后的结构
List<Join> joins = plainSelect.getJoins();
2.9 SetOperationList
用于表示多个select语句通过union,union all连接在一起的联合查询SQL对象
select...from...
union all
select...from...
union all
select...from...
将语句拆分,获取构成它的若干select
SetOperationList operationList = (SetOperationList) selectBody;
List<Select> selectBodyList = operationList.getSelects();
2.10 ParenthesedSelect
用于表示子查询,被小括号包裹的一个查询结构,例如:
(select....from...) as t
“去括号”,得到一个PlainSelect
ParenthesedSelect parenthesedSelect = (ParenthesedSelect) selectBody;
Select select = parenthesedSelect.getSelect();
2.11 FromItem
接口,from后面的SQL结构,ParenthesedSelect,ParenthesedFromItem,Table都是它的实现
FromItem fromItem = plainSelect.getFromItem();
if (fromItem instanceof Table) {
}
else if (fromItem instanceof ParenthesedSelect) {
}
else if (fromItem instanceof ParenthesedFromItem) {
}
2.12 Table
用于表示SQL中的表
2.13 ParenthesedFromItem
小括号包裹的可被查询的结构,但不是子查询,不常用,例如小括号包裹的join:
(tab1 join tab2)
2.14 SelectItem
用于表示select语句中,select和from之间的部分,例如:
select
fun(1, 2) as a,
(select x from ...) as b,
name as c,
exists (...) AS d
from t
List<SelectItem<?>> selectItems = plainSelect.getSelectItems();
selectItems.forEach(selectItem -> {
Expression expression = selectItem.getExpression();
if (expression instanceof Select) {
}
else if (expression instanceof Function) {
}
else if (expression instanceof ExistsExpression) {
}
});
2.15 BinaryExpression
泛指比较符号:and or = >= =<,这种结构左右连接着其他结构。EqualsTo,OrExpression,AndExpression都是它的子类。
获取左右两侧的结构:
BinaryExpression expression = (BinaryExpression) obj;
Expression left = expression.getLeftExpression();
Expression right = expression.getRightExpression();
2.16 InExpression
x in (...)
获取右侧的结构,可能是子查询或(*,*,*...):
InExpression expression = (InExpression) obk;
Expression inExpression = expression.getRightExpression();
2.17 ExistsExpression
exists (...)
获取右侧结构
ExistsExpression expression = (ExistsExpression) obj;
Expression e = expression.getRightExpression() ;
2.18 NotExpression
not,与其他的配合使用,例如:
not in (...)
not exists (...)
获取not后面的结构,会提取出in exists等结构
NotExpression expression = (NotExpression) obj;
Expression e = expression.getExpression();
2.19 Parenthesis
代表小括号()括起来的结构
(...)
去括号,拿到括号中的结构:
Parenthesis expression = (Parenthesis) obj;
Expression e = expression.getExpression();
2.20 Function
函数结构,通常会获取参数,对参数进行操作
fun()
ExpressionList<?> parameters = function.getParameters();
if (parameters != null) {
parameters.forEach(expression -> {
if (expression instanceof Select) {
}
else if (expression instanceof Function) {
}
});
}
2.21 EqualsTo
=
2.22 OrExpression
or
2.23 AndExpression
and
2.24 Join
SQL中连接查询的join结构,从Select中获得。
获取join后的结构,一般可能是表也可能是子查询
FromItem joinItem = join.getRightItem();
判断是否为隐式内连接
join.isSimple();
判断是内/左/右连接
join.isRight();
join.isInner();
join.isLeft();
获取join的on条件
Collection<Expression> originOnExpressions = join.getOnExpressions();
改写join的on条件
join.setOnExpressions(onExpressions);
2.25 Column
用于表示SQL中的字段对象,例如从一个Insert对象获取SQL要添加的全部字段:name,age,tenant_id
INSERT INTO t_user (name, age, tenant_id) VALUES ('liming', 15), ('zhaoying', 16)
List<Column> columns = insert.getColumns();
2.26 UpdateSet
UpdateSet是一种类似xx = xx, ...的结构,出现在update的set后面
update user set username = 5 where id = 1
List<UpdateSet> sets = update.getUpdateSets();
也能在insert语句处理添加的数据冲突的情况时,出现在ON DUPLICATE KEY UPDATE后面
INSERT INTO table_name (col1, col2) VALUES (val1, val2)
ON DUPLICATE KEY UPDATE col1 = val3, col2 = col4 + 1;
List<UpdateSet> duplicateUpdateColumns = insert.getDuplicateUpdateSets();
2.27 ExpressionList
Expression列表,本质上是List<Expression>,当insert语句values后面批量跟了多组值,就能得到这种结构。
('liming', 15), ('zhaoying', 16)
Values values = insert.getValues();
ExpressionList<Expression> expressions = (ExpressionList<Expression>) values.getExpressions();
2.28 ParenthesedExpressionList
继承自ExpressionList,本质上也是List<Expression>,一种带着括号的Expression结构,例如获取insert语句values后面的值就能得到这种结构
('liming', 15)
Values values = insert.getValues();
ExpressionList<Expression> expressions = (ExpressionList<Expression>) values.getExpressions();
if (expressions instanceof ParenthesedExpressionList) {
// ParenthesedExpressionList
} else {
// ExpressionList
}
附:类路径
net.sf.jsqlparser.statement.Statement
net.sf.jsqlparser.statement.select.Select
net.sf.jsqlparser.statement.update.Update
net.sf.jsqlparser.statement.delete.Delete
net.sf.jsqlparser.statement.insert.Insert
net.sf.jsqlparser.schema.Table
net.sf.jsqlparser.expression.Expression
net.sf.jsqlparser.statement.select.ParenthesedSelect
net.sf.jsqlparser.statement.select.SetOperationList
net.sf.jsqlparser.statement.select.SelectItem
net.sf.jsqlparser.expression.BinaryExpression
net.sf.jsqlparser.expression.operators.relational.InExpression
net.sf.jsqlparser.expression.operators.relational.ExistsExpression
net.sf.jsqlparser.expression.NotExpression
net.sf.jsqlparser.expression.Parenthesis
net.sf.jsqlparser.statement.select.ParenthesedFromItem
net.sf.jsqlparser.statement.select.FromItem
net.sf.jsqlparser.expression.Function
net.sf.jsqlparser.expression.operators.relational.EqualsTo
net.sf.jsqlparser.expression.operators.conditional.OrExpression
net.sf.jsqlparser.expression.operators.conditional.AndExpression
net.sf.jsqlparser.statement.select.Join
net.sf.jsqlparser.schema.Column
net.sf.jsqlparser.expression.operators.relational.ExpressionList
net.sf.jsqlparser.expression.operators.relational.ParenthesedExpressionList
SQL解析工具JSQLParser的更多相关文章
- SQL解析工具
面对复杂的SQL可用这个SQL解析工具,分析出用到了哪些表哪些字段: http://107.170.101.241:8080/getTableColumn/
- 几种基于Java的SQL解析工具的比较与调用
1.sqlparser http://www.sqlparser.com/ 优点:支持的数据库最多,除了传统数据库外还支持hive和greenplum一类比较新的数据库,调用比较方便,功能不错 缺点: ...
- Spark之SQL解析(源码阅读十)
如何能更好的运用与监控sparkSQL?或许我们改更深层次的了解它深层次的原理是什么.之前总结的已经写了传统数据库与Spark的sql解析之间的差别.那么我们下来直切主题~ 如今的Spark已经支持多 ...
- 高大上技术之sql解析
Question: 为何sql解析和高大上有关系?Answer:因为数据库永远都是系统的核心,CRUD如此深入码农的内心...如果能把CRUD改造成高大上技术,如此不是造福嘛... CRUD就是Cre ...
- SQL Profiler工具简介
一.SQL Profiler工具简介 SQL Profiler是一个图形界面和一组系统存储过程,其作用如下: 图形化监视SQL Server查询: 在后台收集查询信息: 分析性能: 诊断像死锁之类的问 ...
- 自己实现一个SQL解析引擎
自己实现一个SQL解析引擎 功能:将用户输入的SQL语句序列转换为一个可运行的操作序列,并返回查询的结果集. SQL的解析引擎包含查询编译与查询优化和查询的执行,主要包含3个步骤: 查询分析: 制定逻 ...
- Red Gate系列之六 SQL Test 1.0.12.3 Edition SQL测试工具 完全破解+使用教程
原文:Red Gate系列之六 SQL Test 1.0.12.3 Edition SQL测试工具 完全破解+使用教程 Red Gate系列之六 SQL Test 1.0.12.3 Edition S ...
- SQL优化工具
SQL优化工具 什么是索引? 打个比方,我们在使用MySQL用作查询的时候就好比查字典,索引就好比字典的偏旁部首页.如果没有索引我们查询一个文字就需要一页页的翻,显然这种方式效率很低.如果我们对某一字 ...
- TableML-GUI篇(Excel编译/解析工具)
项目情况 本文接上篇TableML Excel编译/解析工具,本文主要介绍GUI工具的使用,及配置项,如果你想了解此工具更加详细的说明,请阅读上篇文章. 项目地址:https://github.com ...
- SQL解析在美团的应用
https://tech.meituan.com/SQL_parser_used_in_mtdp.html 数据库作为核心的基础组件,是需要重点保护的对象.任何一个线上的不慎操作,都有可能给数据库带来 ...
随机推荐
- 针对N=p^rq分解之初探
针对N=p^r*q分解之初探 论文地址:https://eprint.iacr.org/2015/399.pdf 题目:https://www.nssctf.cn/problem/2016 from ...
- 通过Kube-rbac-proxy保护 Kubernetes 工作负载中的应用容器
1.概述 kube-rbac-proxy 是 Kubernetes 生态中一个专注于"基于角色的访问控制(RBAC)"的轻量级代理组件,通常以 Sidecar 容器的形式部署在 P ...
- Qt 获取本机ipv4地址
Qt 获取本机本地网卡的IPv4地址 本文介绍怎么用Qt去获取本机的ipv4地址 文章目录 Qt 获取本机本地网卡的IPv4地址 用法 用法 话不多说,直接上代码: QHostAddress host ...
- Golang 入门 : 转换
Go中数学运算和比较运算要求包含的值具有相同的类型.如果不是的话,则在尝试运行代码时会报错. 为变量分配新值也是如此.如果所赋值的类型与变量的声明类型不匹配,也会报错. 解决方法是使用转换,它允许你将 ...
- Go语言遍历字符串——获取每一个字符串元素
遍历字符串有下面两种写法. 遍历每一个ASCII字符 遍历 ASCII 字符使用 for 的数值循环进行遍历,直接取每个字符串的下标获取 ASCII 字符,如下面的例子所示. theme := &qu ...
- ISO9126
ISO9126 软件质量模型是评价软件质量的国际标准,由6个特性和27个子特性组成. 中文名 软件质量模型 外文名 ISO9126 属 于 软件产品评价-质量特性 层 次 质量特性 ...
- 10 卷积神经网络CNN原理
1. 全连接层 前文中我们讨论的几乎都是全连接层,也就是在层间,每个神经元都与前一层的所有神经元相连接,如图: 也就是每层的每个feature,都与前一层所有features相关联,是前一层所有fea ...
- c-primer-plus深入解读系列-从二进制到误差:逐行拆解C语言浮点运算中的4008175468544之谜
前言 小提示:阅读本篇内容,至少需要了解double和float的二进制表示规则. 书中的代码示例如下: #include <stdio.h> int main(void) { float ...
- 区块链特辑——solidity语言基础(五)
Solidity语法基础学习 九.实战项目(一): 学以致用 UP主捐款合约 ·合约要求: ·建立时,需将合约的建立者设定成owner(constructor,msg.sender) ·需记录每个观众 ...
- leetcode每日一题:图中的最长环
题目 2360. 图中的最长环 给你一个 n 个节点的 有向图 ,节点编号为 0 到 n - 1 ,其中每个节点 至多 有一条出边. 图用一个大小为 n 下标从 0 开始的数组 edges 表示,节点 ...