博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
JSQLParser 解析 sql select 字段(含对别名的解析)
阅读量:3906 次
发布时间:2019-05-23

本文共 4545 字,大约阅读时间需要 15 分钟。

问大家一个问题:当拿到一个sql,想要获取其中的select字段,是否首先想到的是手写一个来获取查询字段,可是事实并没有想象的那么简单,设想 select 'a' from xx;select id as user_id from xx;select current_date gmt_create from xx;select case when .. from xx;select count(1) from xx;等等,这些语句该怎么解析呢?

推荐使用JSQLParser

JSQLParser是一款开源的SQL语句解析器,使用它可以把SQL语句解析成一组层次分明的java类。JSQLParsers所能解释的SQL语句不受具体数据库的限制,在支持标准SQL的同时,也支持一些特定数据库的方法。如支持Oracle关联语法(+),PostgreSQL的方法using::,以及关系运算符!=,等等。

解析之前,先来看看常见的解析器(expression)有哪些,有利于后面对代码的理解。

1、条件表达式

如:AndExpression(and),OrExpression(or)

2、关系表达式

如:EqualsTo(=),MinorThan(<),GreaterThan(>),……

3、算术表达式

如:Addition(+),Subtraction(-),Multiplication(*),Division(/),……

4、列表达式

如:Column

5、case表达式

如:CaseExpression

6、值表达式

如:StringValue,DateValue,LongValue,DoubleValue,……

7、函数表达式

如:Function

8、参数表达式

如:JdbcParameter,JdbcNameParameter,……

实现代码:

com.github.jsqlparser
jsqlparser
3.1
Map
paramMap = new HashMap<>(queryParamList.size()); for (String queryParam : queryParamList) { paramMap.put(queryParam, "1"); } String parsedSql = generalQueryService.replaceParameterWithValue(querySql, paramMap); try { CCJSqlParserManager parserManager = new CCJSqlParserManager(); Select select = (Select) parserManager.parse(new StringReader(parsedSql)); PlainSelect plain = (PlainSelect) select.getSelectBody(); List
selectItems = plain.getSelectItems(); List
items = new ArrayList<>(); if (selectItems != null) { for (SelectItem selectItem : selectItems) { if (selectItem instanceof SelectExpressionItem) { SelectExpressionItem selectExpressionItem = (SelectExpressionItem) selectItem; String columnName = ""; Alias alias = selectExpressionItem.getAlias(); Expression expression = selectExpressionItem.getExpression(); if (expression instanceof CaseExpression) { // case表达式 columnName = alias.getName(); } else if (expression instanceof LongValue || expression instanceof StringValue || expression instanceof DateValue || expression instanceof DoubleValue) { // 值表达式 columnName = Objects.nonNull(alias.getName()) ? alias.getName() : expression.getASTNode().jjtGetValue().toString(); } else if (expression instanceof TimeKeyExpression) { // 日期 columnName = alias.getName(); } else { if (alias != null) { columnName = alias.getName(); } else { SimpleNode node = expression.getASTNode(); Object value = node.jjtGetValue(); if (value instanceof Column) { columnName = ((Column) value).getColumnName(); } else if (value instanceof Function) { columnName = value.toString(); }else { // 增加对select 'aaa' from table; 的支持 columnName = String.valueOf(value); columnName = columnName.replace("'", ""); columnName = columnName.replace("\"", ""); columnName = columnName.replace("`", ""); } } } columnName = columnName.replace("'", ""); columnName = columnName.replace("\"", ""); columnName = columnName.replace("`", ""); items.add(columnName); } else if (selectItem instanceof AllTableColumns) { AllTableColumns allTableColumns = (AllTableColumns) selectItem; items.add(allTableColumns.toString()); } else { items.add(selectItem.toString()); } } } return StringUtils.join(items, ","); } catch (JSQLParserException e) { // ignore } return null;

代码可能未包含所有的情况,所以当发现问题时,需要查看 expression 按需解决。

转载地址:http://giqen.baihongyu.com/

你可能感兴趣的文章
(ubuntu)在andorid andk工程中使用ccache加速编译速度
查看>>
android graphics system学习资料汇总
查看>>
GDB
查看>>
Oracle RAC Failover 详解
查看>>
[转载]Oracle RAC客户端连接不稳定的解决方法
查看>>
ORA RAC ORA-12545:因目标主机或对象不存在,连接失败!
查看>>
证明两节点能正常failover的sql
查看>>
oracle10g rac 报ora-12545错误的解决方案 转载
查看>>
Linux配置Xmanager
查看>>
IP地址正则表达式
查看>>
对SOAP消息头的处理
查看>>
webservice TCP Monitor
查看>>
Oracle中sysdate的时区偏差
查看>>
【每日一算】旋转有序数组
查看>>
【每日一算】两数之和
查看>>
深入理解Mysql索引底层数据结构与算法
查看>>
B+树算法在mysql中能存多少行数据?
查看>>
【vue学习】—条件判断、循环遍历
查看>>
【vue学习】—slot插槽的使用
查看>>
怎样做研究
查看>>