JSQLParser 解析 sql select 字段(含对别名的解析)

当拿到一个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,……

实现代码:

<dependency>
      <groupId>com.github.jsqlparser</groupId>
      <artifactId>jsqlparser</artifactId>
      <version>3.1</version>
</dependency>
Map<String, String> 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<SelectItem> selectItems = plain.getSelectItems();
            List<String> 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 按需解决。

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
以下是使用jsqlparser解析子查询sql的示例代码: ```java import java.io.StringReader; import java.util.List; import net.sf.jsqlparser.JSQLParserException; import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.parser.CCJSqlParserUtil; import net.sf.jsqlparser.statement.Statement; import net.sf.jsqlparser.statement.select.PlainSelect; import net.sf.jsqlparser.statement.select.Select; import net.sf.jsqlparser.statement.select.SubSelect; public class JSqlParserDemo { public static void main(String[] args) throws JSQLParserException { String sql = "SELECT * FROM (SELECT * FROM table1 WHERE id IN (SELECT id FROM table2)) AS subquery"; Statement statement = CCJSqlParserUtil.parse(sql); Select selectStatement = (Select) statement; PlainSelect plainSelect = (PlainSelect) selectStatement.getSelectBody(); SubSelect subSelect = (SubSelect) plainSelect.getFromItem(); Select subquery = (Select) subSelect.getSelectBody(); PlainSelect subqueryPlainSelect = (PlainSelect) subquery.getSelectBody(); List<Expression> expressions = subqueryPlainSelect.getSelectItems(); for (Expression expression : expressions) { System.out.println(expression.toString()); } } } ``` 上述代码,我们首先将子查询sql语句作为字符串传入JSqlParser进行解析。然后,我们通过获取Select对象和PlainSelect对象来获取子查询的Select对象和PlainSelect对象。最后,我们可以通过获取子查询的PlainSelect对象来获取子查询Select字段

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值