SQL解析处理和扩展开发工具 Java
文章目录
- 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相关推荐
- java项目构建ant_Ant - 项目构建 - 开发工具 - JAVA开源项目 - 开源吧
相关开源项目 Gradle: Gradle是一个基于Groovy的构建工具,它使用Groovy来编写构建脚本,支持依赖管理和多项目创建,类似Maven,但比之简单轻便.为Ivy提供了一个layer,提 ...
- Eclipse、NetBeans、IntelliJ集成开发工具 Java IDE
Eclipse作为开发Java的IDE,从出现到现在已经有几年的时间了,其丰富的特性,操作容易和在提高生产力方面收到了广大开发者的青睐.当然一提到Java IDE,人们不禁会提到其他Java IDE像 ...
- 解析网红营销开发工具,如何快速找到红人
1.hub.wotokol.com 这款红人开发软件里面拥有150w+的红人数据,涵盖了欧美.东南亚.中东.日韩等多个地区 .链接了3大主流平台 YouTube.ins和Tik Tok.拥有2600万 ...
- java常用开发工具
常用源码编辑工具 Java 源代码本质上其实就是普通的文本文件,所以理论上来说任何可以编辑文本文件的编辑器都可以作为我们的 Java 代码编辑工具.比如:Windows 记事本,Mac OS X 下的 ...
- Java学习中的数据库和数据库开发工具
一.数据库 1.数据库,通常是一个戒一组文件,保存了一些符合特定规格的数据,数据库对应的英询单词是DataBase,简称DB:数据库软件称为数据库管理系统,英文简称DBMS,全称为DataBase M ...
- 开发APP的java工具_app傻瓜式开发工具_app开发工具
我想要制作一个app软件需要什么工具 android app开发工具:eclipse or Android Studio ios app开发工具:Xcode eclipse : Eclipse 是一个 ...
- java命名基本规范,和java开发工具相关
命名规范:命名规则: * 工程名: 随意,建议用英文 * 包名:小写 规则:com.baidu.zhidao.service 域名倒写 * 规范: 只能使用英文 数字 _ $ 并且不能以数字开头 * ...
- 《软件开发工具》要点
2019独角兽企业重金招聘Python工程师标准>>> 1.绪论 2.软件开发过程及其组织 3.软件开发工具的理论基础 4.软件开发工具的技术要素 5.软件开发工具的使用与开发 6. ...
- CowNew开源-sql解析引擎和cownewsql阶段成果汇报
很多关心CowNew的朋友纷纷给我发email或者qq留言,说看到最近CowNew开源项目没有动静了,问我是不是虎头蛇尾死掉了.谢谢大家的关心,CowNew没有停止进步的步伐,最近一段时间没有动静是因 ...
- 帆软 JAVA扩展_java报表开发工具FineReport教程之报表设计:单元格扩展
java报表开发工具FineReport教程之报表设计:单元格扩展 报表设计章节适用于对报表业务有一定的了解,需要学习FineReport报表的初学者. 通过该章节的学习,可以掌握设计器的使用,了解报 ...
最新文章
- 康奈尔大学王飞博士:AI处理医疗数据面临的8大挑战
- cmake (3)多个源文件示例
- boost::regex模块实现config_info 来打印正则表达式库配置信息的测试程序
- SQL Server数据库索引的基础知识
- SQLServer之函数简介 1
- (0.2)linux下Mysql的安装配置与管理入门(目录篇)
- 序列每天从0开始_006 Python基础:通用序列操作
- 题解 【NOIP2010】关押罪犯
- 调用webservice,解析返回数据为xml格式的字符串,进行数据绑定
- 数据集制作——使用labelimg制作数据集
- 工具类--生成随机姓名及指定长度随机字符串
- Civil 3D菜单栏不在了怎么办
- hash 算法 (转)
- HTML页面添加背景音乐
- jquery操作样式
- 3、乐趣国学—“色难”
- python在线diff工具在哪_Python - deepdiff
- 在Linux中利用backtrace信息解决程序崩溃问题
- 计算机应用综合知识模拟试卷及答案,计算机应用专业综合知识模拟试卷3
- 斯蒂芬·钦(Stephen Chin)骑着自行车在欧洲巡游
热门文章
- url采集工具_爬山虎采集实战-站长之家网站排行榜
- Java的强、软、弱、虚四种引用类型
- 基于qt制作的音乐播放器,2.0版
- rds基于什么开发_玩物得志: 基于DataWorks+MaxCompute+MC-Hologres 构建大数据平台
- c++ while(condition) 中condition的一些思考
- CentOS 7.6 配置VNC远程访问服务器图形界面
- SAP中程序从服务器下载所对应的文件
- 《Go Web编程实战派——从入门到精通》学习笔记之第1章 Go基础入门
- Windows可视化编程C++基础知识
- 重庆大学计算机软件,重庆大学计算机辅助设计制造软件采购.DOC