这里给出使用的druid坐标
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid</artifactId>
<version>1.1.16</version>
</dependency>
注意:druid不同版本结果可能会有细微差异。
然后以Postgres数据库的语法进行解析。其实解析大致上都相同,数据库的差异对解析影响不是很大,最重要的还是思想。
要使用druid进行SQL解析,你需要先明白SQL的执行顺序,SQL大致的执行顺序
FROM -> WHERE -> GROUP BY -> HAVING -> SELECT -> ORDER BY
当然这也只是个大致的顺序,具体细节还需自己去探索。
我们先用最简单的SQL来看看什么是SQL解析。
public static void main(String[] args) {
String sql = "select * from t";
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, JdbcConstants.POSTGRESQL);
SQLStatement sqlStatement = sqlStatements.get(0);
System.out.println(sqlStatement);
}
这里的sqlStatements对象我们暂时不用管它是什么,主要看sqlStatement对象,这里面封装了SQL语句的全部信息。
现在我们使用debug查看sqlStatement对象里面到底是什么如图
其实这里的sqlStatement就是大家说的AST(抽象语法树),这里面没有什么重要的信息,就一个dbType,可以看到数据库类型。然后我们继续看这个select
看上去也没有什么,我们继续点开query
这里面看上去信息就很全,这里面的各种关键字都是用来存放SQL语句中的信息的,由于刚才SQL中只有select和from信息,所以我们可以看到其他信息比如order by 都是 null,我们在点看 selectList 和 from
可以看到我们的select * 和from t中的信息都被存放了进去。
由此我们就可以知道,druid解析,实际上就是把SQL语句中的信息全部都解析出来放在这个sqlStatement中
然后我们只需去解析这个sqlStatement对象就可以了,至于sqlStatement对象怎么解析,后面的博客会说到,这里只是入门。
下面我们再来解析个复杂的SQL
public static void main(String[] args) {
String sql = "select seq,remark,grade from student where 1=1 group by grade order by seq";
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, JdbcConstants.POSTGRESQL);
SQLStatement sqlStatement = sqlStatements.get(0);
System.out.println(sqlStatement);
}
同样的我们还是debug看sqlStatement对象,这次我们直接看query对象
怎么样,是不是我们SQL的信息这里面都有,我们暂时先不用管这些信息的数据结构是什么样的,只用看到这些信息都有就行。
我们先点开这个orderBy 看看里面是什么
orderBy对象里面有个items是一个List对象,这里面存放你order by 后面的字段,一个字段就是一个items的元素
再看一下这个groupBy
它和orderBy类似也是一个group by后面一个字段就是一个items对象
不同的是它还有个having对象,这个在你的SQL有having关键字时就会填充进去。
其实还有其他的解析方式,比如visitor,但我觉得没有直接解析这个statement对象来的直接。
就比如这样
public static void main(String[] args) {
String sql = "with t as (select * from t) select seq,remark,grade from student where 1=1 group by grade order by seq";
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(sql, JdbcConstants.POSTGRESQL);
SQLStatement sqlStatement = sqlStatements.get(0);
PGSchemaStatVisitor visitor = new PGSchemaStatVisitor();
sqlStatement.accept(visitor);
System.out.println(sqlStatement);
}
这样你就可以debug查看visitor,有兴趣可以看看。
其实SQL解析在很多公司都会用到,但是发现博客很少,大多都是个入门,刚好我使用到了,经过4个月的开发,算是有了一些经验,想写在这留个笔记,方便以后回忆,也希望给要入手SQL解析的人有个帮助。