峰之博纹 - Pelephone个人博客

一个利用正则表达式解析单句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);
        }
    }
}
posted @ 2011-11-27 10:21  Pelephone  阅读(5167)  评论(0编辑  收藏  举报