JeeGit

 找回密码
 立即注册
搜索
查看: 90|回复: 4

一个利用正则表达式解析单句SQL的类SqlParser

[复制链接]

6

主题

20

帖子

74

积分

版主

Rank: 7Rank: 7Rank: 7

积分
74
发表于 2020-12-20 21:26:45 | 显示全部楼层 |阅读模式
回复

使用道具 举报

6

主题

20

帖子

74

积分

版主

Rank: 7Rank: 7Rank: 7

积分
74
 楼主| 发表于 2020-12-20 21:35:10 | 显示全部楼层
String text = "select * from [admin] where aa=1 and cc='b' order by aa desc ";    
               Regex reg = null;
               reg = new Regex(@"\s+from\s+.*?(\s+where\s+|\s+order\s+|\s+group\s+)|\s+from\s+.+", RegexOptions.IgnoreCase);
               string table = reg.Match(text).Value;
               table = Regex.Replace(table.ToLower(), @"\s+from\s+|\s+where\s+|\[|\]|\s+order\s+|\s+group\s+", "");
               reg = new Regex(@"select\s+.*?\s+from\s+", RegexOptions.IgnoreCase);
               string field = reg.Match(text).Value;
               field = Regex.Replace(field.ToLower(), @"select\s+|\s+from\s+|\[|\]", "");
               reg = new Regex(@"\s+where\s+.*?(\s+order\s+|\s+group\s+)|\s+where\s+.+", RegexOptions.IgnoreCase);
               string condition = reg.Match(text).Value;
               condition = Regex.Replace(condition.ToLower(), @"\s+where\s+|\s+order\s+|\s+group\s+|\[|\]", "");
               reg = new Regex(@"\s+order\s+by\s+.*?\s(desc|asc)|\s+order\s+by\s+.*?\s", RegexOptions.IgnoreCase);
               string order = reg.Match(text).Value;
               order = Regex.Replace(order.ToLower(),@"\s+order\s+by\s+|\[|\]", "");
回复

使用道具 举报

6

主题

20

帖子

74

积分

版主

Rank: 7Rank: 7Rank: 7

积分
74
 楼主| 发表于 2020-12-20 21:35:37 | 显示全部楼层
回复

使用道具 举报

6

主题

20

帖子

74

积分

版主

Rank: 7Rank: 7Rank: 7

积分
74
 楼主| 发表于 2020-12-20 21:47:37 | 显示全部楼层
几种基于Java的SQL解析工具的比较与调用

1、sqlparser

http://www.sqlparser.com/

优点:支持的数据库最多,除了传统数据库外还支持hive和greenplum一类比较新的数据库,调用比较方便,功能不错

缺点:收费,500$起

2、Apache Calcite

一个构建JDBC或者ODBC访问数据库的框架,通过自定义一些adapter通过sql访问任意类型的数据

优点:开源

缺点:sql解析只是一小部分功能,且只支持通用的文法树,无法对不同数据库提供本地化支持

3、druid

阿里的一个开源项目,其实是个JDBC,但是可以通过这个JDBC统计通过它提交的各种sql执行情况等信息,对提交sql进行监控统计

主页:https://github.com/alibaba/druid

我们用到的SQL-Parser是它的一个组件:

https://github.com/alibaba/druid/wiki/SQL-Parser

支持数据库不算少:

db2
mysql
odps
oracle
phoenix
postgresql
sqlserver
transact

不过部分语法支持还处于开发中,比如,不支持解析postgresql的begin/commit语法,不支持group by 1, 2这种指定字段的语法。。。-_||

编译:

一开始懒得安装maven使用javac编译,结果出了一堆代码中包含的中文编码问题,花时间研究编码不如乖乖下载安装maven……-_-

在源码根目录下直接执行mvn:

mvn install -Dmaven.javadoc.skip=true -Dmaven.test.skip=true
编译后代码目录多出target子目录,里面有class和代码文件的jar包

调用很简单

复制代码
1 package parse;
2
3 import java.util.Iterator;
4 import java.util.List;
5 import java.util.Map;
6 import java.util.Set;
7
8 import com.alibaba.druid.sql.SQLUtils;
9 import com.alibaba.druid.sql.ast.SQLStatement;
10 import com.alibaba.druid.sql.dialect.postgresql.visitor.PGSchemaStatVisitor;
11 import com.alibaba.druid.stat.TableStat.*;
12 import com.alibaba.druid.stat.*;
14 import com.alibaba.druid.util.JdbcConstants;
15  
16
17 public class testparse {
18  
19     public static void main(String[] args) {
20  
21         String sql= ""
22                 + "insert into tar select * from boss_table bo, ("
23                     + "select a.f1, ff from emp_table a "
24                     + "inner join log_table b "
25                     + "on a.f2 = b.f3"
26                     + ") f "
27                     + "where bo.f4 = f.f5 "
28                     + "group by bo.f6 , f.f7 having count(bo.f8) > 0 "
29                     + "order by bo.f9, f.f10;"
30                     + "select func(f) from test1; "
31                     + "";
32         String dbType = JdbcConstants.POSTGRESQL;
33  
34         //格式化输出
35         String result = SQLUtils.format(sql, dbType);
36         System.out.println(result); // 缺省大写格式
37         List<SQLStatement> stmtList = SQLUtils.parseStatements(sql, dbType);
38  
39         //解析出的独立语句的个数
40         System.out.println("size is:" + stmtList.size());
41         for (int i = 0; i < stmtList.size(); i++) {
42  
43             SQLStatement stmt = stmtList.get(i);
44            
45             PGSchemaStatVisitor visitor = new PGSchemaStatVisitor();
46             stmt.accept(visitor);
47             Map<String, String> aliasmap = visitor.getAliasMap();
48             for (Iterator iterator = aliasmap.keySet().iterator(); iterator.hasNext();) {
49                 String key = iterator.next().toString();
50                 System.out.println("[ALIAS]" + key + " - " + aliasmap.get(key));
51             }
52             Set<Column> groupby_col = visitor.getGroupByColumns();
53             //
54             for (Iterator iterator = groupby_col.iterator(); iterator.hasNext();) {
55                 Column column = (Column) iterator.next();
56                 System.out.println("[GROUP]" + column.toString());
57             }
58             //获取表名称
59             System.out.println("table names:");
60             Map<Name, TableStat> tabmap = visitor.getTables();
61             for (Iterator iterator = tabmap.keySet().iterator(); iterator.hasNext();) {
62                 Name name = (Name) iterator.next();
63                 System.out.println(name.toString() + " - " + tabmap.get(name).toString());
64             }
65             //System.out.println("Tables : " + visitor.getCurrentTable());
66             //获取操作方法名称,依赖于表名称
67             System.out.println("Manipulation : " + visitor.getTables());
68             //获取字段名称
69             System.out.println("fields : " + visitor.getColumns());
70         }
71  
72     }
73  
74 }
复制代码
回复

使用道具 举报

6

主题

20

帖子

74

积分

版主

Rank: 7Rank: 7Rank: 7

积分
74
 楼主| 发表于 2020-12-20 21:52:54 | 显示全部楼层
本帖最后由 姚海陆 于 2020-12-20 21:54 编辑

https://github.com/JSQLParser/JSqlParserhttp://jsqlparser.sourceforge.net/example.php
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|JeeGit

GMT+8, 2021-1-17 20:25 , Processed in 0.067715 second(s), 17 queries .

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表