首页 > 数据库 >【JSQLParser库】SQL解析神器

【JSQLParser库】SQL解析神器

时间:2025-01-20 14:46:02浏览次数:1  
标签:name 神器 role JSQLParser SQL id select user

环境搭建:

SpringBoot3.2.5

1. 简介

JSQLParser是一个开源的Java库,它专注于SQL语句的解析与操作。该库能够将SQL语句转换为抽象语法树(AST),使开发者能够轻松地分析、修改和重新生成SQL查询。它是基于 JavaCC 构建的 SQL 语句解析器。它将 SQL 语句转换为可遍历的 Java 类层次结构。

JSQLParser支持多种SQL方言,包括但不限于MySQL、PostgreSQL、Oracle和SQL Server,这使得它能够在多种数据库环境中发挥作用。通过JSQLParser,开发者可以提取SQL语句中的表名、字段名、条件等信息,甚至动态地修改SQL查询,如添加字段或修改条件。

接下来,我将详细的介绍JSQLParser的使用。

2. 实战案例

2.1 环境准备

目前该JSQLParser最新版本是5.1。

<dependency>
  <groupId>com.github.jsqlparser</groupId>
  <artifactId>jsqlparser</artifactId>
  <version>5.1</version>
</dependency>

引入该包下面我们就可以使用该工具进行SQL语句的解析处理了。

2.2 简单解析

public static void example1() throws Exception {
  String sqlStr = "select id, name, age from user where id = 6";
  PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr);
  List<SelectItem<?>> selects = select.getSelectItems() ;
  System.err.printf("select字段: %s%n", selects) ;
  Table table = (Table) select.getFromItem();
  System.err.printf("表名: %s%n", table.getName()) ;
}

这里我们解析一个非常简单的SQL语句,运行结果:

select字段: [id, name, age]
表名: user

上面的示例中,我们获取SQL语句中 select子句(查询了哪些字段)以及获取当前查询的表名信息。

为了获得API的指导,我们使用JSQLFormatter可视化Java对象的遍历树:

具体通过如下链接查看:

http://217.160.215.75:8080/jsqlformatter/JSQLFormatter/demo.html

通过该地址,输入SQL后,能展示当前SQL的层次结构。

2.3 查找SQL中所有表

类net.sf.jsqlparser.util.TablesNamesFinder可用于从查询或表达式中返回所有表名。

String sqlStr = "select id, (select name from role r where r.uid = u.id) from user u";
Set<String> tables = TablesNamesFinder.findTables(sqlStr) ;
System.err.println(tables) ;

输出结果

[role, user]

再看下面的SQL同样也能正确的读取所有的表

var sqlStr = "select id, name from user u where u.role_id = (select id from role r where r.name = 'admin')";
var tables = TablesNamesFinder.findTables(sqlStr) ;
System.err.println(tables) ;

该语句也能正确的所有所有的表名。

连接查询

sqlStr = "select id, name, role_name from user u left join role r on(u.role_id = r.id)";
tables = TablesNamesFinder.findTables(sqlStr) ;

输出结果

[role, user]

以上列举了3个示例演示了获取SQL中所有参与的表信息。

2.4 获取where子句

下面我们通过一个比较复杂的SQL语句来解析where子句信息:

public static void example3() throws Exception {
  String  sqlStr = """
        SELECT
          id,
          name,
          role_name 
        FROM
          USER u
          LEFT JOIN role r ON ( u.role_id = r.id ) 
        WHERE
          name = 'pack' 
          AND age = 20 
          AND (email = 'xxx' or state = 1)
      """;
  PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr);
  Expression where = select.getWhere() ;
  System.err.println(where) ;
  print(where) ;
}
private static void print(Expression expression) {
  if (expression instanceof ComparisonOperator co) {
    System.out.println(expression) ;
    return ;
  }
  if (expression instanceof BinaryExpression be) {
    Expression leftExpression = be.getLeftExpression() ;
    print(leftExpression) ;
    Expression rightExpression = be.getRightExpression() ;
    print(rightExpression) ;
  }  else if (expression instanceof ParenthesedExpressionList pe) {
    pe.stream().forEach(e -> {
      print((Expression) e) ;
    }) ;
  } 
}

输出结果

解析出了where子句中的所有条件。

2.5 构建修改SQL

public static void example5() throws Exception {  
  Table table = new Table()
      .withName("user")
      .withAlias(new Alias("t", false)) ;

  Column nameColumn = new Column().withColumnName("name");
  StringValue nameValue = new StringValue("admin") ;
  Expression whereExpression = new EqualsTo()
      .withLeftExpression(nameColumn)
      .withRightExpression(nameValue) ;

  PlainSelect select = new PlainSelect()
      .addSelectItems(new Column("id"), new Column("age"), new Column("name"))
      .withFromItem(table)
      .withWhere(whereExpression);
  System.err.println(select.toString()) ;
}

输出SQL语句:

SELECT id, age, name FROM user t WHERE name = 'admin'

使用流畅的API非常轻松的构建任何SQL语句。

2.6 错误处理

public static void example6() throws Exception {
  CCJSqlParser parser = new CCJSqlParser(
      "select * from user; select from; select * from role" ) ;
  Statements statements = parser.Statements() ;
  System.err.println(statements.size()) ;
  statements.stream().forEach(System.out::println);
}

当我们执行上面的代码后,程序抛出如下错误:

我们的第二条SQL是错误的。

这种情况下,如果你希望即便错了也继续向后解析,那么你可以通过如下的设置:

Statements statements = parser.withErrorRecovery(true)
  .Statements() ;

使用withErrorRecovery方法,将继续到下一个语句分隔符并返回一个空语句。

SELECT * FROM user
null
SELECT * FROM role

你也可以如下的方式进行错误的处理:

Statements statements = CCJSqlParserUtil.parseStatements(
    "select * from user; select from; select * from role;"
    , parser -> parser.withUnsupportedStatements() );
statements.stream().forEach(System.out::println);

输出结果

SELECT * FROM user
select from
SELECT * FROM role

将错误的语句原样返回。

原创 Springboot实战案例锦集 Spring全家桶实战案例源码

标签:name,神器,role,JSQLParser,SQL,id,select,user
From: https://www.cnblogs.com/o-O-oO/p/18681154

相关文章

  • 深入解析:Postgres 和 MySQL 的核心差异与选择建议
    几十年来,关系数据库为无数应用程序提供了支持,它们仍然是许多现代系统的支柱。说到可用于生产的选项,有两种最为广泛使用的数据库,即PostgreSQL和MySQL。两者都提供了可靠的性能、可靠性和社区支持,但它们在处理数据的方式、功能集和配置难易程度方面存在明显差异。了解这些细微差......
  • 【SQL Server】Service Broker——在单个数据库建完成对话
    一般来说,在SQLServer中调用存储过程,是同步的。如果一个操作比较长,那么我们我们希望执行异步操作。消息队列概念。消息队列在SQLServer李,是一种存储消息的结构。消息生产者将消息发送到队列中,而消息消费者则从队列中读取并处理消息。这种机制实现了应用程序组件之间的异步通信,......
  • MySql操作指南7-数据验证与错误处理
    在使用Go语言访问MySQL数据库时,数据验证和错误处理是确保应用程序稳定性与数据完整性的核心环节。此外,日志管理对于问题追踪和系统调试具有重要作用。本文将介绍数据验证、错误处理以及日志记录与追踪的相关内容。通过这些技术,可以显著提高系统的健壮性和可维护性。 1、......
  • 【SQL精彩语句】分拆列值
    /*分拆列值原著:邹建改编:爱新觉罗.毓华(十八年风雨,守得冰山雪莲花开)2007-12-16广东深圳有表tb,如下:idvalue----------------------1aa,bb2aaa,bbb,ccc欲按id,分拆value列,分拆后结果如下:idvalue-------------------1aa1bb2aaa2bbb2ccc*/--1.旧的解决方法(sql......
  • MySQL的count()方法慢
    COUNT()方法概述COUNT() 方法是MySQL中常用的聚合函数之一,用于统计满足特定条件的记录数量。虽然 COUNT()方法功能强大,但在处理大数据量时,执行速度可能会变慢。这篇文章将详细分析 COUNT()方法变慢的原因,并提供优化方案。COUNT()方法慢的原因1.表数据量大当表中记录数非......
  • MySQL里面的时间与UNIX时间戳,解决2038年问题的思考
    当前时间:NOW()当前时间:NOW()函数,传入参数是一个整数类型,传入参数可以是:空(0)、1~6;代表时间精度(秒后面的精度)。SELECTNOW(),NOW(0),NOW(1),NOW(2),NOW(3),NOW(4),NOW(5),NOW(6);如下:NOW()NOW(0)NOW(1)NOW(2)2025-01-2009:47:012025-01-2009:47:012025-01-......
  • MySQL不香吗,为啥还要Elasticsearch?
    一、先说说MySQL有啥优点MySQL这玩意,咱们都熟。行存储的代表,关系型数据库的中流砥柱。它有啥好处?老铁,太多了:数据一致性:事务支持那是杠杠的,ACID四大天王保护你数据不丢失。结构化查询:SQL语句一出,啥复杂查询都能搞定,分组、排序、子查询,随便玩。成熟稳健:发展几十年,社区大,文档多,踩......
  • 数据迁移丨借助 AI 从 PostgreSQL 到 GreatSQL
    数据迁移丨借助AI从PostgreSQL到GreatSQL本文将介绍如何从PostgreSQL到GreatSQL的数据迁移,并运用AI协助迁移更加方便。迁移的方式有很多,例如:pg_dump:导出SQL文件,修改后导入GreatSQL数据库。COPY:导出txt文本文件,导入GreatSQL数据库。pg2mysql:从PostgreSQL迁......
  • 数据库基础——mysql数据库
    一、数据库简介    数据库:数据库是一个按数据结构来存储和管理数据的计算机软件系统。简单来说,数据库是用来存放数据的。    常见数据库及端口mysql(3306):关系型数据库  mssal(1433)  oracle(1521)  db2(9500)  postgresql(5432)       ......
  • Cursor从小白到高手-.cursorignore 为什么如此重要?-一期教学-AI编程神器,让你一个顶十
    0.前言父文章导航(配合更佳):Cursor从小白到高手-下载及基本配置子文章或相关文章导航(不是目录导航哦~):如此重要的CursorRules配置,你不会不知道吧!!不配置.cursorignore,cursor性能毁一半!!!Docs讲解(计划中~~)Chat&Composer(计划中~~~)文章持续迭代中,敬请期待~~~~~Cursor......