一个利用正则表达式解析单句SQL的类SqlParser
先看要解析的样例SQL语句:
select * from dual
SELECT * frOm dual
Select C1,c2 From tb
select c1,c2 from tb
select count(*) from t1
select c1,c2,c3 from t1 where condi1=1
Select c1,c2,c3 From t1 Where condi1=1
select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2
Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2
select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2
Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2
Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3

解析效果之一(isSingleLine=false):
原SQL为select * from dual
解析后的SQL为
select
*
from
dual

原SQL为SELECT * frOm dual
解析后的SQL为
select
*
from
dual

原SQL为Select C1,c2 From tb
解析后的SQL为
select
C1,c2
from
tb

原SQL为select c1,c2 from tb
解析后的SQL为
select
c1,c2
from
tb

原SQL为select count(*) from t1
解析后的SQL为
select
count(*)
from
t1

原SQL为select c1,c2,c3 from t1 where condi1=1
解析后的SQL为
select
c1,c2,c3
from
t1
where
condi1=1

原SQL为Select c1,c2,c3 From t1 Where condi1=1
解析后的SQL为
select
c1,c2,c3
from
t1
where
condi1=1

原SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2
解析后的SQL为
select
c1,c2,c3
from
t1,t2
where
condi3=3 or condi4=5
order by
o1,o2

原SQL为Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2
解析后的SQL为
select
c1,c2,c3
from
t1,t2
where
condi3=3 or condi4=5
order by
o1,o2

原SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2
解析后的SQL为
select
c1,c2,c3
from
t1,t2,t3
where
condi1=5 and condi6=6 or condi7=7
group by
g1,g2

原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2
解析后的SQL为
select
c1,c2,c3
from
t1,t2,t3
where
condi1=5 and condi6=6 or condi7=7
group by
g1,g2

原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3
解析后的SQL为
select
c1,c2,c3
from
t1,t2,t3
where
condi1=5 and condi6=6 or condi7=7
group by
g1,g2,g3
order by
g2,g3

解析效果之二(isSingleLine=true):
原SQL为select * from dual
解析后的SQL为
select
*
from
dual

原SQL为SELECT * frOm dual
解析后的SQL为
select
*
from
dual

原SQL为Select C1,c2 From tb
解析后的SQL为
select
C1,
c2
from
tb

原SQL为select c1,c2 from tb
解析后的SQL为
select
c1,
c2
from
tb

原SQL为select count(*) from t1
解析后的SQL为
select
count(*)
from
t1

原SQL为select c1,c2,c3 from t1 where condi1=1
解析后的SQL为
select
c1,
c2,
c3
from
t1
where
condi1=1

原SQL为Select c1,c2,c3 From t1 Where condi1=1
解析后的SQL为
select
c1,
c2,
c3
from
t1
where
condi1=1

原SQL为select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2
where
condi3=3 or
condi4=5
order by
o1,
o2

原SQL为Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2
where
condi3=3 or
condi4=5
order by
o1,
o2

原SQL为select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2,
t3
where
condi1=5 and
condi6=6 or
condi7=7
group by
g1,
g2

原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2,
t3
where
condi1=5 and
condi6=6 or
condi7=7
group by
g1,
g2

原SQL为Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3
解析后的SQL为
select
c1,
c2,
c3
from
t1,
t2,
t3
where
condi1=5 and
condi6=6 or
condi7=7
group by
g1,
g2,
g3
order by
g2,
g3

使用的类SqlParser,你可以拷贝下来使用之:
package com.sitinspring.common.sqlFormatter;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
* SQL语句解析器类
* @author: sitinspring(junglesong@gmail.com)
* @date: 2008-3-12
*/
public class SqlParser{
/**
* 逗号
*/
private static final String Comma = ",";

/**
* 四个空格
*/
private static final String FourSpace = " ";

/**
* 是否单行显示字段,表,条件的标识量
*/
private static boolean isSingleLine=true;

/**
* 待解析的SQL语句
*/
private String sql;

/**
* SQL中选择的列
*/
private String cols;

/**
* SQL中查找的表
*/
private String tables;

/**
* 查找条件
*/
private String conditions;

/**
* Group By的字段
*/
private String groupCols;

/**
* Order by的字段
*/
private String orderCols;

/**
* 构造函数
* 功能:传入构造函数,解析成字段,表,条件等
* @param sql:传入的SQL语句
*/
public SqlParser(String sql){
this.sql=sql.trim();

parseCols();
parseTables();
parseConditions();
parseGroupCols();
parseOrderCols();
}

/**
* 解析选择的列
*
*/
private void parseCols(){
String regex="(select)(.+)(from)";
cols=getMatchedString(regex,sql);
}

/**
* 解析选择的表
*
*/
private void parseTables(){
String regex="";

if(isContains(sql,"\\s+where\\s+")){
regex="(from)(.+)(where)";
}
else{
regex="(from)(.+)($)";
}

tables=getMatchedString(regex,sql);
}

/**
* 解析查找条件
*
*/
private void parseConditions(){
String regex="";

if(isContains(sql,"\\s+where\\s+")){
// 包括Where,有条件

if(isContains(sql,"group\\s+by")){
// 条件在where和group by之间
regex="(where)(.+)(group\\s+by)";
}
else if(isContains(sql,"order\\s+by")){
// 条件在where和order by之间
regex="(where)(.+)(order\\s+by)";
}
else{
// 条件在where到字符串末尾
regex="(where)(.+)($)";
}
}
else{
// 不包括where则条件无从谈起,返回即可
return;
}

conditions=getMatchedString(regex,sql);
}

/**
* 解析GroupBy的字段
*
*/
private void parseGroupCols(){
String regex="";

if(isContains(sql,"group\\s+by")){
// 包括GroupBy,有分组字段

if(isContains(sql,"order\\s+by")){
// group by 后有order by
regex="(group\\s+by)(.+)(order\\s+by)";
}
else{
// group by 后无order by
regex="(group\\s+by)(.+)($)";
}
}
else{
// 不包括GroupBy则分组字段无从谈起,返回即可
return;
}

groupCols=getMatchedString(regex,sql);
}

/**
* 解析OrderBy的字段
*
*/
private void parseOrderCols(){
String regex="";

if(isContains(sql,"order\\s+by")){
// 包括GroupBy,有分组字段
regex="(order\\s+by)(.+)($)";
}
else{
// 不包括GroupBy则分组字段无从谈起,返回即可
return;
}

orderCols=getMatchedString(regex,sql);
}

/**
* 从文本text中找到regex首次匹配的字符串,不区分大小写
* @param regex: 正则表达式
* @param text:欲查找的字符串
* @return regex首次匹配的字符串,如未匹配返回空
*/
private static String getMatchedString(String regex,String text){
Pattern pattern=Pattern.compile(regex,Pattern.CASE_INSENSITIVE);

Matcher matcher=pattern.matcher(text);

while(matcher.find()){
return matcher.group(2);
}

return null;
}

/**
* 看word是否在lineText中存在,支持正则表达式
* @param lineText
* @param word
* @return
*/
private static boolean isContains(String lineText,String word){
Pattern pattern=Pattern.compile(word,Pattern.CASE_INSENSITIVE);
Matcher matcher=pattern.matcher(lineText);
return matcher.find();
}

public String toString(){
// 无法解析则原样返回
if(cols==null && tables==null && conditions==null && groupCols==null && orderCols==null ){
return sql;
}

StringBuffer sb=new StringBuffer();
sb.append("原SQL为"+sql+"\n");
sb.append("解析后的SQL为\n");

for(String str:getParsedSqlList()){
sb.append(str);
}

sb.append("\n");

return sb.toString();
}

/**
* 在分隔符后加上回车
* @param str
* @param splitStr
* @return
*/
private static String getAddEnterStr(String str,String splitStr){
Pattern p = Pattern.compile(splitStr,Pattern.CASE_INSENSITIVE);

// 用Pattern类的matcher()方法生成一个Matcher对象
Matcher m = p.matcher(str);
StringBuffer sb = new StringBuffer();

// 使用find()方法查找第一个匹配的对象
boolean result = m.find();

// 使用循环找出模式匹配的内容替换之,再将内容加到sb里
while (result) {
m.appendReplacement(sb, m.group(0) + "\n ");
result = m.find();
}
// 最后调用appendTail()方法将最后一次匹配后的剩余字符串加到sb里;
m.appendTail(sb);

return FourSpace+sb.toString();
}

/**
* 取得解析的SQL字符串列表
* @return
*/
public List<String> getParsedSqlList(){
List<String> sqlList=new ArrayList<String>();

// 无法解析则原样返回
if(cols==null && tables==null && conditions==null && groupCols==null && orderCols==null ){
sqlList.add(sql);
return sqlList;
}

if(cols!=null){
sqlList.add("select\n");
if(isSingleLine){
sqlList.add(getAddEnterStr(cols,Comma));
}
else{
sqlList.add(FourSpace+cols);
}
}

if(tables!=null){
sqlList.add(" \nfrom\n");

if(isSingleLine){
sqlList.add(getAddEnterStr(tables,Comma));
}
else{
sqlList.add(FourSpace+tables);
}
}

if(conditions!=null){
sqlList.add(" \nwhere\n");

if(isSingleLine){
sqlList.add(getAddEnterStr(conditions,"(and|or)"));
}
else{
sqlList.add(FourSpace+conditions);
}
}

if(groupCols!=null){
sqlList.add(" \ngroup by\n");

if(isSingleLine){
sqlList.add(getAddEnterStr(groupCols,Comma));
}
else{
sqlList.add(FourSpace+groupCols);
}
}

if(orderCols!=null){
sqlList.add(" \norder by\n");

if(isSingleLine){
sqlList.add(getAddEnterStr(orderCols,Comma));
}
else{
sqlList.add(FourSpace+orderCols);
}
}

return sqlList;
}

/**
* 设置是否单行显示表,字段,条件等
* @param isSingleLine
*/
public static void setSingleLine(boolean isSingleLine) {
SqlParser.isSingleLine = isSingleLine;
}

/**
* 测试
* @param args
*/
public static void main(String[] args){
List<String> ls=new ArrayList<String>();
ls.add("select * from dual");
ls.add("SELECT * frOm dual");
ls.add("Select C1,c2 From tb");
ls.add("select c1,c2 from tb");
ls.add("select count(*) from t1");
ls.add("select c1,c2,c3 from t1 where condi1=1 ");
ls.add("Select c1,c2,c3 From t1 Where condi1=1 ");
ls.add("select c1,c2,c3 from t1,t2 where condi3=3 or condi4=5 order by o1,o2");
ls.add("Select c1,c2,c3 from t1,t2 Where condi3=3 or condi4=5 Order by o1,o2");
ls.add("select c1,c2,c3 from t1,t2,t3 where condi1=5 and condi6=6 or condi7=7 group by g1,g2");
ls.add("Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2");
ls.add("Select c1,c2,c3 From t1,t2,t3 Where condi1=5 and condi6=6 or condi7=7 Group by g1,g2,g3 order by g2,g3");

for(String sql:ls){
System.out.println(new SqlParser(sql));
//System.out.println(sql);
}
}
}

转载于:https://www.cnblogs.com/NRabbit/archive/2008/08/25/1736204.html

个利用正则表达式解析单句SQL的类SqlParser相关推荐

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

    原SQL为select * from dual 解析后的SQL为 select * from dual 原SQL为SELECT * frOm dual 解析后的SQL为 select * from d ...

  2. 解析单句sql_单句SQL语句的解析方案。

    最近想改写一下数据库交互的底层代码,搞来两篇sql解析的方案文章.不管这么多,先转了再说- 数据是程序处理的主要内容,它一般存储在关系型数据库中,要操作它们最终必须要通过SQL语句来完成,因此,解读分 ...

  3. java解析lrc_java中用正则表达式解析LRC文件

    跟着Mars老师 一起写android中的Mp3播放器 真是受益匪浅 再次感谢老师的无私奉献 不过其中问题也确实不少 感觉老师的代码重构做的不够 其中对LRC文件的解析也弄的比较马虎 今天特意花了一天 ...

  4. 【Java 解析全国地址】Java 利用正则表达式完美解析全国省市区地址

    Java 利用正则表达式完美解析全国省市区地址 一.问题场景描述 最近在项目中遇到了一个全国地址解析的一个场景,前端会传来一个字符串,后端需自动解析出 xx省xx市xx区+详细地址 的这种格式. 因为 ...

  5. jsqlparser解析SQL工具类(转载)

    JSQLParser官网地址:http://jsqlparser.sourceforge.net/ JSQLParserGitHub地址:https://github.com/JSQLParser/J ...

  6. 解析利用wsdl.exe生成webservice代理类的详解

    利用wsdl.exe生成webservice代理类: 根据提供的wsdl生成webservice代理类 1.开始->程序->Visual Studio 2010 命令提示 2.输入如下红色 ...

  7. 【超详总结/理解:正则表达式】特点/元字符/正则表达式中的标志位-flag/RegExp/重复操作与后向引用/匹配模式/表达邮箱/正则表达式对象的方法/利用正则表达式限制网页表单里的文本框输入内容

    文章目录 正则表达式: 正则表达式的用途 正则表达式的组成-元字符 正则表达式的特点 正则表达式中的标志位-flag JavaScript中的正则表达式解析 RegExp 定义 RegExp RegE ...

  8. java sql注入 正则表达式_Java防止SQL注入(转)

    一.SQL注入简介 SQL注入是比较常见的网络攻击方式之一,它不是利用操作系统的BUG来实现攻击,而是针对程序员编程时的疏忽,通过SQL语句,实现无帐号登录,甚至篡改数据库. 二.SQL注入攻击的总体 ...

  9. spark日志存储路径为mysql_利用Spark解析Tomcat日志,并将统计结果存入Mysql数据库...

    本文试图实现的需求场景为:以学习Spark知识点为目的,编写Scala利用Spark解析800M的tomcat日志文件,打印一段时间内ERROR级别记录的前10行,统计每分钟的日志记录数,并将统计结果 ...

  10. Mybatis解析动态sql原理分析

    前言 废话不多说,直接进入文章. 我们在使用mybatis的时候,会在xml中编写sql语句. 比如这段动态sql代码: <update id="update" parame ...

最新文章

  1. mysql insert 锁
  2. springboot mybatis ehcache_SpringBoot入门建站全系列(十四)集成Redis缓存
  3. 橱柜高度与身高对照表_下一套房子装修,橱柜就照这样打,布局尺寸这么详细,不信不好用...
  4. 动态后台获取_后台管理系统的权限以及vue处理权限的思路
  5. 高精度减法(洛谷-P2142)
  6. linux输密码复制,在Linux下用scp复制文件无需输入密码的技巧
  7. 软件测试的出路到底在哪?
  8. MIT 量子计算的编程语言 Twist
  9. win10相机计算机无法使用,win10相机无法使用完美解决方法
  10. w ndows系统启动日志ID,WIN7日志总能看到 特殊登陆 事件ID 4672,是怎么回事?
  11. while True:just do it
  12. 【故事】跟零计算机基础的房东女儿讲了一下午的中间人劫持京东事件后,她感激涕零,决定给我免除房租(上)...
  13. 哪个软件能代替斐讯路由_斐讯路由(老版本无需登录)
  14. 动漫免费在线观看,实时更新,资源全
  15. Java 实现简单的发红包代码
  16. 嵌入式Linux(5):驱动开发网络调试驱动设备的Linux系统移植
  17. 怎么在阿里妈妈投放广告?--人人有责-- .
  18. 地球坐标系 (WGS-84) 到火星坐标系 (GCJ-02) 的转换算法
  19. 静态工作点是什么?有什么作用?
  20. Matlab入门实践

热门文章

  1. mysql创建触发器怎么保存_如何创建使用mysql触发器?
  2. 第490篇--Accessing the Domain info is denied in IIS.
  3. System Operations on AWS - Lab 7 - CloudFormation
  4. 阿里百川SDK初始化失败 错误码是203
  5. Sonar安装和常见问题解决
  6. composer.install
  7. GNU Radio 之 rtl-sdr
  8. 6个文件写出Tomcat核心功能(新手必看)
  9. vue+django2.0.2-rest-framework 生鲜项目(五)
  10. 【2017级面向对象程序设计】作业二