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

from:http://www.blogjava.net/sitinspring/archive/2008/03/14/186372.html

先看要解析的样例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);
 }
 }
}

上一篇:用正则表达式捕获标识符——随便说
下一篇:一条匹配SQL语句的正则

发表评论


评论内容 (必填):