文章目录

  • Druid_SQL_AST
  • SQL解析
  • SQL翻译 MySQL语句翻译成Oracle
  • SQL语句格式化
  • SQL语句验证
  • 获取表名、查询字段、查询条件
  • 修改表名
  • 为SQL增加额外的where条件
  • 解析select项、表信息、条件信息

Druid_SQL_AST

AST是abstract syntax tree的缩写,也就是抽象语法树。和所有的Parser一样,Druid Parser会生成一个抽象语法树。
本文重点不是讲解AST,想要了解这方面的内容可以参见官方文档:
https://github.com/alibaba/druid/wiki/Druid_SQL_AST
本文主要是在接触Druid中发现其中有很多拿来即用的SQL相关工具组件,秉着学习积累的态度于是将这些组件进行整理记录。如果在之后有类似的需要可以拿来即用,或者深入了解后进行扩展开发。

导入依赖:

    <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.2.9</version></dependency>

SQL解析

通过SQLUtils产生List,通过下面简单的代码就可以解析出SQL语句AST对象

 DbType dbType = JdbcConstants.MYSQL;String sql="select * from dual where 1=1 order by create_time desc limit 10,10";List<SQLStatement> statementList = SQLUtils.parseStatements(sql, dbType);for (SQLStatement sqlStatement : statementList) {System.out.println(sqlStatement);}

SQL翻译 MySQL语句翻译成Oracle

SQL 翻译,即将一种方言,翻译成另一种。比如输入 MySQL 的 SQL 脚本,使用 MySQL 的 Parser 进行解析,再使用 Oracle 的 Visitor 进行遍历输出,就可以完成 MySQL 脚本到 Oracle 脚本的翻译:

/***  SQL翻译,将MySQL语句翻译成Oracle* @author zhangyu* @date 2022/5/22**/@Testpublic void  test12(){// MySQL的语言String sql="select * from dual where 1=1 order by create_time desc limit 10,10";List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, DbType.mysql);// 将MySQL方言翻译为Oracle的String oracleSql = SQLUtils.toSQLString(sqlStatements, DbType.oracle);System.out.println(oracleSql);}


Tips:上面只演示了MySQL转换Oracle的,其他的类型可以参考DbType这个枚举类。

SQL语句格式化

Druid SQL Parser提供了格式化代码的工具类。这个是基于语义分析做的SQL格式化功能,比其他的SQL格式化做的更智能,效果更好

package com.alibaba.druid.sql;public class SQLUtils {String format(String sq, String dbType);String format(String sq, String dbType, FormatOption option);
}

其中dbType支持mysql/postgresql/odps/oracle/db2/sqlserver
option缺省有SQLUtils.DEFAULT_FORMAT_OPTION(大写)、SQLUtils.DEFAULT_LCASE_FORMAT_OPTION(小写)两种可以选择,也可按需要定制化。

    /***  SQL格式化* @author zhangyu* @date 2022/5/22**/@Testpublic void test13(){String sql = "select t1.id ,t2.name  from t1 ,t2  where 1=1  and t1.id=t2.id and t2.name='ZY' order by create_time desc limit 10,10";String result = SQLUtils.format(sql, JdbcConstants.MYSQL);System.out.println(result); // 缺省大写格式System.out.println("-------------------------------------------------------");String result_lcase = SQLUtils.format(sql, JdbcConstants.MYSQL, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION);System.out.println(result_lcase); // 小写格式}

SQL语句验证

SQLUtils.parseStatements会根据输入的SQL语句以及方言进行AST语法的分析,我们可以利用这个去判断验证SQL是否是正确的,比较简单的方式就是直接try-catch捕获异常。下面的实例中故意多写了一个where,解析失败

/***  验证SQL的正确性* @author zhangyu* @date 2022/5/22**/@Testpublic void test14(){String sql = "select t1.id ,t1.name  from t1  t2 where   ";try{List<SQLStatement> statementList = SQLUtils.parseStatements(sql, DbType.mysql);for (SQLStatement sqlStatement : statementList) {System.out.println(sqlStatement);}}catch (Exception e){log.error("解析SQL失败",e);e.printStackTrace();}}

获取表名、查询字段、查询条件

SQLUtils.parseStatements会根据输入的SQL语句以及方言进行AST语法的分析,在处理过程中会将SQL语句进行解析分析,并且提供了一些外部的访问方式去获取解析后的信息,结合特定方言的MySqlSchemaStatVisitor对象可以获取这些信息

/****  获取表名、查询字段、查询条件*/@Testpublic void test15(){DbType dbType = JdbcConstants.MYSQL;String sql = "select\n" +"    -- 注释\n" +"    t1.id,\n" +"    t2.name\n" +"from\n" +"    table1 t1,\n" +"    table2 t2,\n" +"    table3 t3\n" +"where\n" +"    t1.id = t2.user_id\n" +"    and t3.user_id = t1.id\n" +"    and t1.name = 'zy'\n" +"    and t2.address = '安徽合肥'";List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);for (SQLStatement stmt : stmtList) {MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();stmt.accept(visitor);// 获取表名System.out.println("获取表名");Map<TableStat.Name, TableStat> tables = visitor.getTables();Set<TableStat.Name> tableNameSet = tables.keySet();for (TableStat.Name name : tableNameSet) {String tableName = name.getName();System.out.println(tableName);}System.out.println("获取查询列名");// 获取查询列名Collection<TableStat.Column> columns = visitor.getColumns();for (TableStat.Column column : columns) {if (column.isSelect()) {String table = column.getTable();String name = column.getName();System.out.println(table + "." + name);}}System.out.println("获取查询条件");// 获取查询条件List<TableStat.Condition> conditions = visitor.getConditions();for (TableStat.Condition condition : conditions) {TableStat.Column column = condition.getColumn();String table = column.getTable();String name = column.getName();String operator = condition.getOperator();System.out.println();System.out.print(table + "." + name + operator);List<Object> values = condition.getValues();for (Object value : values) {System.out.print(value);}}}}

修改表名

所有的AST节点都支持Visitor模式,需要自定义逻辑,可以实现相应的ASTVisitorAdapter派生类,在下面的实例中我们自定义了CustomTableAliasVisitor 然后实现的方法是参数为SQLExprTableSource 。对应接口SQLASTVisitor存在很多空接口,我们可以根据需要修改表名信息,字段信息,关联信息等等,根据需求实现对应的方法。

【实例】在下面的实例中我修改了t2的表名为newTableName。这个应用在很多的场景都适用,比如查询逻辑变动,比如将表改成了视图,再比如分表后的一些查询实现等等

 /*** 修改表名*/@Testpublic void test16() {DbType dbType = JdbcConstants.MYSQL;String sql = "select t1.name ,t2.name  from t1 ,t2 ";List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);CustomTableAliasVisitor visitor = new CustomTableAliasVisitor();for (SQLStatement stmt : stmtList) {stmt.accept(visitor);}String sqlString = SQLUtils.toSQLString(stmtList, dbType);System.out.println(sqlString);}/*** 自定义处理器,自定义表名信息*/static class CustomTableAliasVisitor extends MySqlASTVisitorAdapter {@Overridepublic boolean visit(SQLExprTableSource x) {// 别名String alias = x.getAlias();// 表名String tableName = x.getTableName();if ("t2".equals(tableName)) {// 修改表2的表名x.setExpr("newTableName");//修改别名x.setAlias("t2");}return true;}}

为SQL增加额外的where条件

对于一些SQL场景下,希望手动添加额外的条件,那么可以通过 SQLUtils.addCondition的方式添加扩展条件

    /*** 为SQL添加额外的条件** @author zhangyu* @date 2022/5/22**/@Testpublic void test2() {String sql = "select * from dual where 1=1 order by create_time desc limit 10,10";// 添加AND条件String s = SQLUtils.addCondition(sql, "address = 'AnHui HeFei' ", DbType.mysql);// 添加OR条件String s1 = SQLUtils.addCondition(s, "name = 'AnHui' ", SQLBinaryOperator.BooleanOr, false, DbType.mysql);System.out.println(s1);}

解析select项、表信息、条件信息

@Testpublic void test17() {String sql = "select t1.name ,t2.address  from t1 ,t2  where t1.id=t2.user_id and t1.name =? and t2.name =?";//使用mysql解析MySqlStatementParser sqlStatementParser = new MySqlStatementParser(sql);//解析select查询SQLSelectStatement sqlStatement = (SQLSelectStatement) sqlStatementParser.parseSelect();SQLSelect sqlSelect = sqlStatement.getSelect();//获取sql查询块SQLSelectQueryBlock sqlSelectQuery = (SQLSelectQueryBlock) sqlSelect.getQuery();StringBuffer out = new StringBuffer();//创建sql解析的标准化输出SQLASTOutputVisitor sqlastOutputVisitor = SQLUtils.createFormatOutputVisitor(out, null, JdbcUtils.MYSQL);//解析select项out.delete(0, out.length());for (SQLSelectItem sqlSelectItem : sqlSelectQuery.getSelectList()) {if (out.length() > 1) {out.append(",");}sqlSelectItem.accept(sqlastOutputVisitor);}System.out.println("查询字段信息 " + out);//解析fromout.delete(0, out.length());sqlSelectQuery.getFrom().accept(sqlastOutputVisitor);System.out.println("表信息 " + out);//解析whereout.delete(0, out.length());sqlSelectQuery.getWhere().accept(sqlastOutputVisitor);System.out.println("查询条件信息 " + out);}

SQL解析处理和扩展开发工具 Java相关推荐

  1. java项目构建ant_Ant - 项目构建 - 开发工具 - JAVA开源项目 - 开源吧

    相关开源项目 Gradle: Gradle是一个基于Groovy的构建工具,它使用Groovy来编写构建脚本,支持依赖管理和多项目创建,类似Maven,但比之简单轻便.为Ivy提供了一个layer,提 ...

  2. Eclipse、NetBeans、IntelliJ集成开发工具 Java IDE

    Eclipse作为开发Java的IDE,从出现到现在已经有几年的时间了,其丰富的特性,操作容易和在提高生产力方面收到了广大开发者的青睐.当然一提到Java IDE,人们不禁会提到其他Java IDE像 ...

  3. 解析网红营销开发工具,如何快速找到红人

    1.hub.wotokol.com 这款红人开发软件里面拥有150w+的红人数据,涵盖了欧美.东南亚.中东.日韩等多个地区 .链接了3大主流平台 YouTube.ins和Tik Tok.拥有2600万 ...

  4. java常用开发工具

    常用源码编辑工具 Java 源代码本质上其实就是普通的文本文件,所以理论上来说任何可以编辑文本文件的编辑器都可以作为我们的 Java 代码编辑工具.比如:Windows 记事本,Mac OS X 下的 ...

  5. Java学习中的数据库和数据库开发工具

    一.数据库 1.数据库,通常是一个戒一组文件,保存了一些符合特定规格的数据,数据库对应的英询单词是DataBase,简称DB:数据库软件称为数据库管理系统,英文简称DBMS,全称为DataBase M ...

  6. 开发APP的java工具_app傻瓜式开发工具_app开发工具

    我想要制作一个app软件需要什么工具 android app开发工具:eclipse or Android Studio ios app开发工具:Xcode eclipse : Eclipse 是一个 ...

  7. java命名基本规范,和java开发工具相关

    命名规范:命名规则: * 工程名: 随意,建议用英文 * 包名:小写 规则:com.baidu.zhidao.service 域名倒写 * 规范: 只能使用英文 数字 _ $ 并且不能以数字开头 * ...

  8. 《软件开发工具》要点

    2019独角兽企业重金招聘Python工程师标准>>> 1.绪论 2.软件开发过程及其组织 3.软件开发工具的理论基础 4.软件开发工具的技术要素 5.软件开发工具的使用与开发 6. ...

  9. CowNew开源-sql解析引擎和cownewsql阶段成果汇报

    很多关心CowNew的朋友纷纷给我发email或者qq留言,说看到最近CowNew开源项目没有动静了,问我是不是虎头蛇尾死掉了.谢谢大家的关心,CowNew没有停止进步的步伐,最近一段时间没有动静是因 ...

  10. 帆软 JAVA扩展_java报表开发工具FineReport教程之报表设计:单元格扩展

    java报表开发工具FineReport教程之报表设计:单元格扩展 报表设计章节适用于对报表业务有一定的了解,需要学习FineReport报表的初学者. 通过该章节的学习,可以掌握设计器的使用,了解报 ...

最新文章

  1. 康奈尔大学王飞博士:AI处理医疗数据面临的8大挑战
  2. cmake (3)多个源文件示例
  3. boost::regex模块实现config_info 来打印正则表达式库配置信息的测试程序
  4. SQL Server数据库索引的基础知识
  5. SQLServer之函数简介 1
  6. (0.2)linux下Mysql的安装配置与管理入门(目录篇)
  7. 序列每天从0开始_006 Python基础:通用序列操作
  8. 题解 【NOIP2010】关押罪犯
  9. 调用webservice,解析返回数据为xml格式的字符串,进行数据绑定
  10. 数据集制作——使用labelimg制作数据集
  11. 工具类--生成随机姓名及指定长度随机字符串
  12. Civil 3D菜单栏不在了怎么办
  13. hash 算法 (转)
  14. HTML页面添加背景音乐
  15. jquery操作样式
  16. 3、乐趣国学—“色难”
  17. python在线diff工具在哪_Python - deepdiff
  18. 在Linux中利用backtrace信息解决程序崩溃问题
  19. 计算机应用综合知识模拟试卷及答案,计算机应用专业综合知识模拟试卷3
  20. 斯蒂芬·钦(Stephen Chin)骑着自行车在欧洲巡游

热门文章

  1. url采集工具_爬山虎采集实战-站长之家网站排行榜
  2. Java的强、软、弱、虚四种引用类型
  3. 基于qt制作的音乐播放器,2.0版
  4. rds基于什么开发_玩物得志: 基于DataWorks+MaxCompute+MC-Hologres 构建大数据平台
  5. c++ while(condition) 中condition的一些思考
  6. CentOS 7.6 配置VNC远程访问服务器图形界面
  7. SAP中程序从服务器下载所对应的文件
  8. 《Go Web编程实战派——从入门到精通》学习笔记之第1章 Go基础入门
  9. Windows可视化编程C++基础知识
  10. 重庆大学计算机软件,重庆大学计算机辅助设计制造软件采购.DOC