您当前的位置:首页 > 电脑百科 > 数据库 > 百科

SQL解析利器JSqlParser

时间:2023-04-21 13:56:01  来源:今日头条  作者:Esgoon

JSqlParser是一个与RDBMS无关的SQL语句解析器,支持多种方言,例如Oracle、SQL Server、MySQL、MariaDB、PostgreSQL、H2等。

JSqlParser将SQL语句转换为JAVA类的可遍历层次结构,还可以用于通过API从Java代码创建SQL语句。现在普遍使用的MyBatis-plus以及分页插件PageHelper都是借助JSqlParser实现SQL解析的。

JSqlParser源码主要包括以下几类对象:

  • expression:SQL构建相关类,比如Function、EqualsTo、AndExpression、InExpression等表达式用于构建SQL。
  • parser:SQL解析相关类,比如CCJSqlParserUtil、CCJSqlParserManager、抽象语法树对象等。
  • schema:主要存放数据库schema相关的类 ,比如Database、Table、Column等。
  • statement:封装了数据库操作对象,create、insert、delete、select、drop、alter、truncate等。
  • util:各种工具类、不同DB版本、SQL标准等处理类,如SelectUtils、DatabaseType等。

 

解析SQL

对于下列SQL语句:

SELECT name, age, score FROM user WHERE id=1;

转换为Java对象层次结构为:

 

解析SQL代码实例:

public static void parseSQL() {
    //Select语句样本
    String sql1 = "select t1.f1,t1.f2,t2.id,count(*) from table1 t1 left join table2 t2 right join (select * from table3) t3 where t1.id='10' or (t1.id between 1 and 3 and t1.id>'12') group by t.f1 order by t.f1 desc,tf2 asc limit 1,20";
    //Insert语句样本
    String sql2 = "insert into table(f1,f2) values (1,2)";
    //Create语句样本
    String sql3 = "CREATE TABLE `sys_user` (n" +
        "  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '编号',n" +
        "  `name` varchar(200) DEFAULT '' COMMENT '名称',n" +
        "  `age` tinyint(4) DEFAULT NULL COMMENT '年龄',n" +
        "  `create_by` varchar(64) DEFAULT '' COMMENT '创建者',n" +
        "  `create_time` datetime DEFAULT NULL COMMENT '创建时间',n" +
        "  `update_by` varchar(64) DEFAULT '' COMMENT '更新者',n" +
        "  `update_time` datetime DEFAULT NULL COMMENT '更新时间',n" +
        "  `remark` varchar(500) DEFAULT NULL COMMENT '备注',n" +
        "  PRIMARY KEY (`id`)n" +
        ") ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='用户表';";
    try {
        //处理Select语句
        Select select = (Select) CCJSqlParserUtil.parse(sql1);
        TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
        List<String> tableList = tablesNamesFinder.getTableList(select);
        // 获取到查询sql中的所有表名
        System.out.println("表名:" + tableList);
           
        //处理Insert语句
        Insert insert = (Insert) CCJSqlParserUtil.parse(sql2);
        System.out.println("插入的表" + insert.getTable());
        System.out.println("插入的列" + insert.getColumns());
        System.out.println("插入的值" + insert.getItemsList());
           
        //处理Create Table语句
        Statement statement = CCJSqlParserUtil.parse(sql3);
        if (statement instanceof CreateTable) {
            CreateTable createTable = ((CreateTable) statement);
            Table table = createTable.getTable();
            //通过columnDefinition进而可以获取列名、数据类型等
            List<ColumnDefinition> columnDefinitions = createTable.getColumnDefinitions();
            System.out.println(table);
            System.out.println(columnDefinitions);
        }
    } catch (Exception e) {
        e.printStackTrace();
    }
}

输出如下:

表名:[table1, table2, table3]
插入的表table
插入的列[f1, f2]
插入的值(1, 2)
`sys_user`
[`id` bigint (20) NOT NULL AUTO_INCREMENT COMMENT '编号', `username` varchar (200) DEFAULT '' COMMENT '名称', `age` tinyint (4) DEFAULT NULL COMMENT '年龄', `create_by` varchar (64) DEFAULT '' COMMENT '创建者', `create_time` datetime DEFAULT NULL COMMENT '创建时间', `update_by` varchar (64) DEFAULT '' COMMENT '更新者', `update_time` datetime DEFAULT NULL COMMENT '更新时间', `remark` varchar (500) DEFAULT NULL COMMENT '备注']

 

创建SQL

/**
 * 创建SQL查询语句
 *
 * @throws JSQLParserException
 */
public static void createSQL() throws JSQLParserException {
  // 单表全量
  Table table = new Table("sys_user");
  //查询所有列
  Select select = SelectUtils.buildSelectFromTable(table);
  // SELECT * FROM sys_user
  System.out.println(select);

    // 指定列查询
    Select buildSelectFromTableAndExpressions = SelectUtils.buildSelectFromTableAndExpressions(new Table("test"), new Column("col1"), new Column("col2"));
    // SELECT col1, col2 FROM sys_user
    System.out.println(buildSelectFromTableAndExpressions);

    // WHERE =
    EqualsTo equalsTo = new EqualsTo(); // 等于表达式
    // 设置表达式左边值
    equalsTo.setLeftExpression(new Column(table, "user_id")); 
    // 设置表达式右边值
    equalsTo.setRightExpression(new StringValue("123456"));
    // 转换为更细化的Select对象
    PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
    plainSelect.setWhere(equalsTo);
    // SELECT * FROM sys_user WHERE sys_user.user_id = '123456'
    System.out.println(plainSelect);

    // WHERE  != <>
    NotEqualsTo notEqualsTo = new NotEqualsTo();
    notEqualsTo.setLeftExpression(new Column(table, "user_id")); // 设置表达式左边值
    notEqualsTo.setRightExpression(new StringValue("123456"));// 设置表达式右边值
    PlainSelect plainSelectNot = (PlainSelect) select.getSelectBody();
    plainSelectNot.setWhere(notEqualsTo);
    System.out.println(plainSelectNot);//  SELECT * FROM sys_user WHERE sys_user.user_id <> '123456'

    // 其他运算符, 参考上面代码添加表达式即可
    GreaterThan gt = new GreaterThan(); // ">"
    GreaterThanEquals geq = new GreaterThanEquals(); // ">="
    MinorThan mt = new MinorThan(); // "<"
    MinorThanEquals leq = new MinorThanEquals();// "<="
    IsNullExpression isNull = new IsNullExpression(); // "is null"
    isNull.setNot(true);// "is not null"
    LikeExpression nlike = new LikeExpression();
    nlike.setNot(true); // "not like"
    Between bt = new Between();
    bt.setNot(true);// "not between"

    // WHERE LIKE
    LikeExpression likeExpression = new LikeExpression(); // 创建Like表达式对象
    likeExpression.setLeftExpression(new Column("username")); // 表达式左边
    likeExpression.setRightExpression(new StringValue("张%")); // 右边表达式
    PlainSelect plainSelectLike = (PlainSelect) select.getSelectBody();
    plainSelectLike.setWhere(likeExpression);
    System.out.println(plainSelectLike); // SELECT * FROM sys_user WHERE username LIKE '张%'

    // WHERE IN
    Set<String> deptIds = Sets.newLinkedHashSet(); // 创建IN范围的元素集合
    deptIds.add("0001");
    deptIds.add("0002");
    ItemsList itemsList = new ExpressionList(deptIds.stream().map(StringValue::new).collect(Collectors.toList())); // 把集合转变为JSQLParser需要的元素列表
    InExpression inExpression = new InExpression(new Column("dept_id "), itemsList); // 创建IN表达式对象,传入列名及IN范围列表
    PlainSelect plainSelectIn = (PlainSelect) select.getSelectBody();
    plainSelectIn.setWhere(inExpression);
    System.out.println(plainSelectIn); // SELECT * FROM sys_user WHERE dept_id  IN ('0001', '0002')

    // WHERE BETWEEN AND
    Between between = new Between();
    between.setBetweenExpressionStart(new LongValue(18)); // 设置起点值
    between.setBetweenExpressionEnd(new LongValue(30)); // 设置终点值
    between.setLeftExpression(new Column("age")); // 设置左边的表达式,一般为列
    PlainSelect plainSelectBetween = (PlainSelect) select.getSelectBody();
    plainSelectBetween.setWhere(between);
    System.out.println(plainSelectBetween); // SELECT * FROM sys_user WHERE age BETWEEN 18 AND 30

    //  WHERE AND 多个条件结合,都需要成立
    AndExpression andExpression = new AndExpression(); // AND 表达式
    andExpression.setLeftExpression(equalsTo); // AND 左边表达式
    andExpression.setRightExpression(between);  // AND 右边表达式
    PlainSelect plainSelectAnd = (PlainSelect) select.getSelectBody();
    plainSelectAnd.setWhere(andExpression);
    System.out.println(plainSelectAnd); //  SELECT * FROM sys_user WHERE sys_user.user_id = '123456' AND age BETWEEN 18 AND 30

    //  WHERE OR 多个条件满足一个条件成立返回
    OrExpression orExpression = new OrExpression();// OR 表达式
    orExpression.setLeftExpression(equalsTo); // OR 左边表达式
    orExpression.setRightExpression(between);  // OR 右边表达式
    PlainSelect plainSelectOr = (PlainSelect) select.getSelectBody();
    plainSelectOr.setWhere(orExpression);
    System.out.println(plainSelectOr); // SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30

    // ORDER BY 排序
    OrderByElement orderByElement = new OrderByElement(); // 创建排序对象
    orderByElement.isAsc(); //  设置升序排列 从小到大
    orderByElement.setExpression(new Column("col01")); // 设置排序字段
    PlainSelect plainSelectOrderBy = (PlainSelect) select.getSelectBody();
    plainSelectOrderBy.addOrderByElements(orderByElement);
    // SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30 ORDER BY col01
    System.out.println(plainSelectOrderBy); 
}

输出如下:

SELECT * FROM sys_user
SELECT col1, col2 FROM sys_user
SELECT * FROM sys_user WHERE sys_user.user_id = '123456'
SELECT * FROM sys_user WHERE sys_user.user_id <> '123456'
SELECT * FROM sys_user WHERE username LIKE '张%'
SELECT * FROM sys_user WHERE dept_id  IN ('0001', '0002')
SELECT * FROM sys_user WHERE age BETWEEN 18 AND 30
SELECT * FROM sys_user WHERE sys_user.user_id = '123456' AND age BETWEEN 18 AND 30
SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30
SELECT * FROM sys_user WHERE sys_user.user_id = '123456' OR age BETWEEN 18 AND 30 ORDER BY col01


Tags:SQL   点击:()  评论:()
声明:本站部分内容及图片来自互联网,转载是出于传递更多信息之目的,内容观点仅代表作者本人,如有任何标注错误或版权侵犯请与我们联系(Email:2595517585@qq.com),我们将及时更正、删除,谢谢。
▌相关推荐
JSqlParser是一个与RDBMS无关的SQL语句解析器,支持多种方言,例如Oracle、SQL Server、MySQL、MariaDB、PostgreSQL、H2等。JSqlParser将SQL语句转换为Java类的可遍历层次结构,...【详细内容】
2023-04-21  Tags: SQL  点击:(0)  评论:(0)  加入收藏
一、 前言导读 TiDB作为NewSQL,其在对MySQL(SQL92协议)的兼容上做了很多,MySQL作为当下使用较广的事务型数据库,在IT界尤其是互联网间使用广泛,那么对于开发人员来说,1)两个数据库产...【详细内容】
2023-04-17  Tags: SQL  点击:(18)  评论:(0)  加入收藏
1、整体介绍对于 select * from table 中的星号,我们再熟悉不过了:它告诉 MySQL 返回表所有字段的内容。MySQL 服务端收到 select 语句之后,会在 server 层把星号展开为表中的...【详细内容】
2023-04-17  Tags: SQL  点击:(16)  评论:(0)  加入收藏
本文给大家总结如何让SQL起飞(优化)一、SQL写法优化在SQL中,很多时候不同的SQL代码能够得出相同结果。从理论上来说,我们认为得到相同结果的不同SQL之间应该有相同的性能,但遗憾...【详细内容】
2023-04-14  Tags: SQL  点击:(13)  评论:(0)  加入收藏
1 MySQL 常见查询技巧查看MYSQL正在运行中的进程:show processlist; 查看Mysql占用空间大小:show table status from some_database;使用示例: Mysql日期模糊查询使用:date_form...【详细内容】
2023-04-13  Tags: SQL  点击:(9)  评论:(0)  加入收藏
之前松哥写过一个 MySQL 系列,但是当时是基于 MySQL5.7 的,最近有空在看 MySQL8 的文档,发现和 MySQL5.7 相比还是有不少变化,同时 MySQL 又是小伙伴们在面试时一个非常重要的知...【详细内容】
2023-04-13  Tags: SQL  点击:(8)  评论:(0)  加入收藏
什么是游标?游标(cursor)是一个存储在MySQL服务器上的数据库查询, 它不是一条SELECT语句,而是被该语句检索出来的结果集。在存储了游 标之后,应用程序可以根据需要滚动或浏览其中...【详细内容】
2023-04-13  Tags: SQL  点击:(12)  评论:(0)  加入收藏
批量更新一般在批处理系统或者定时任务中比较常见,常见的诉求就是对表中多条数据进行更新(待更新的值是不一样的,这个区别于update ... where in(...))1.利用case ... when ......【详细内容】
2023-04-12  Tags: SQL  点击:(10)  评论:(0)  加入收藏
关系型数据库还有一个重要的概念:Join(连接)。使用Join有好处,也会坏处,只有我们明白了其中的原理,才能更多的使用Join。切记不可以:业务之上,再复杂的查询也在一个连表语句中完成。...【详细内容】
2023-04-12  Tags: SQL  点击:(9)  评论:(0)  加入收藏
一:需求背景产品签到活动需求,对于日活量不高的程序,可以直接使用MySQL去处理,当然数据量不大的话,签到一次,数据库签到表保存一条记录,也是可以的。但是如果类似京东等商城,那种签...【详细内容】
2023-04-11  Tags: SQL  点击:(10)  评论:(0)  加入收藏
▌简易百科推荐
JSqlParser是一个与RDBMS无关的SQL语句解析器,支持多种方言,例如Oracle、SQL Server、MySQL、MariaDB、PostgreSQL、H2等。JSqlParser将SQL语句转换为Java类的可遍历层次结构,...【详细内容】
2023-04-21  Esgoon  今日头条  Tags:SQL   点击:(0)  评论:(0)  加入收藏
一、 前言导读 TiDB作为NewSQL,其在对MySQL(SQL92协议)的兼容上做了很多,MySQL作为当下使用较广的事务型数据库,在IT界尤其是互联网间使用广泛,那么对于开发人员来说,1)两个数据库产...【详细内容】
2023-04-17    京东云开发者  Tags:SQL   点击:(18)  评论:(0)  加入收藏
Part 01 什么是图形数据库 ​图形数据库是NoSQL数据库的一种类型,起源于欧拉理论和图理论,对应英文名是Graph Database。一种专用于创建和处理图形的专业化单一用途平台,图形...【详细内容】
2023-04-17  移动Labs  微信公众号  Tags:图形数据库   点击:(12)  评论:(0)  加入收藏
单节点模式(Standalone,不推荐用于生产环境)standalone模式即单节点模式,指在服务器上只部署一个 mongod 进程用于读写数据。优点是部署简单,可以快速完成部署,缺点是无容灾。只推...【详细内容】
2023-04-16  路多辛  今日头条  Tags:MongoDB   点击:(13)  评论:(0)  加入收藏
本文给大家总结如何让SQL起飞(优化)一、SQL写法优化在SQL中,很多时候不同的SQL代码能够得出相同结果。从理论上来说,我们认为得到相同结果的不同SQL之间应该有相同的性能,但遗憾...【详细内容】
2023-04-14  wayn111  今日头条  Tags:SQL   点击:(13)  评论:(0)  加入收藏
我们在写SQL代码时,只要有排序,首先想到的肯定是ORDER BY,以至于好多小伙伴觉得排序多简单啊。今天就给大家介绍四个你不怎么常用排序函数,他们就是SQL Server排序中经常用到的R...【详细内容】
2023-04-11  SQL数据库开发  微信公众号  Tags:SQL   点击:(11)  评论:(0)  加入收藏
PostgreSQL数据库表在删除数据后磁盘空间未释放,该怎么办? 主流的压缩表工具有哪些?该如何选择?1、从空间未释放说起近期生产环境出现一张表占用size已达2T,且会定期删除记录,但...【详细内容】
2023-04-10  数据库干货铺  环球网  Tags:PostgreSQL   点击:(28)  评论:(0)  加入收藏
一、背景关于sql调参数、数据倾斜可以搜到很多文章,本文主要讲解常见的SQL开发场景、“奇葩”SQL写法并深入执行计划,带你了解如何快速写出高效率SQL。二、高效写法1、union直...【详细内容】
2023-04-04  dbaplus社群    Tags:SQL   点击:(8)  评论:(0)  加入收藏
基于SQL的数据可视化和数据挖掘是目前业内非常流行的一种数据分析方法,它可以帮助企业快速地了解和分析自身的数据,从而制定更加科学和有效的业务决策。在本文中,我将以一个实...【详细内容】
2023-04-04  树言树语Tree  今日头条  Tags:数据可视化   点击:(19)  评论:(0)  加入收藏
最近做项目遇到一个问题,外键关联查询,返回长度为1,但是值为 All elements are null没数据。有两张表,分别为a表有数据,b表无数据。select b.* from a as a left join b as b on...【详细内容】
2023-03-30  青木川30  今日头条  Tags:Mybatis   点击:(30)  评论:(0)  加入收藏
站内最新
站内热门
站内头条