春風博客

          春天里,百花香...

          導航

          <2008年3月>
          2425262728291
          2345678
          9101112131415
          16171819202122
          23242526272829
          303112345

          統計

          公告

          MAIL: junglesong@gmail.com
          MSN: junglesong_5@hotmail.com

          Locations of visitors to this page

          常用鏈接

          留言簿(11)

          隨筆分類(224)

          隨筆檔案(126)

          個人軟件下載

          我的其它博客

          我的鄰居們

          最新隨筆

          搜索

          積分與排名

          最新評論

          閱讀排行榜

          評論排行榜

          一個利用正則表達式解析單句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 on 2008-03-14 20:08 sitinspring 閱讀(7615) 評論(10)  編輯  收藏 所屬分類: 個人作品

          評論

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2008-03-15 20:42 lingos

          你這解析了干嘛用?  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2008-03-16 11:48 如坐春風

          @lingos

          用在我的一個小工具中。
          http://download.enet.com.cn/html/030212008012701.html  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2008-03-17 09:30 CowNew開源團隊

          Great job!
          另外也可以使用我們CowNewSQL中的SQL解析器,已經可以解析非常復雜的SQL語句了。CowNewSQL的SQL解析器部分可以單獨拿出來使用。  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2008-03-17 20:00 如坐春風

          @CowNew開源團隊

          謝謝。

          你們的解析器我剛來Blogjava就聽說過,也有想用的念頭,只是不知道它是免費的還是協議的,能否用在我的小沒有開源的工具中。 也沒去問你們,自己寫的權當是練手了。以后我會考慮使用貴團隊的SQL解析器的。

            回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2008-03-17 20:03 CowNew開源團隊

          @如坐春風
          可以使用的。我們的解析器是LGPL協議的,所以可以用在私有軟件中。具體可以參考LGPL協議,:)。如果在使用過程中有問題可以和我們聯系,:)。  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2008-03-17 20:07 如坐春風

          @CowNew開源團隊

          回帖好快啊!

          你們的地址我記下了,忙完這陣我一定會拜訪的。  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2008-04-26 11:04 wsand

          select c1,c2,c3 from t1,t2 order by o1,o2
          沒有where,測試一下  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser 2011-05-05 15:11 謝宇

          既然是簡單表達式我也不說太難的例子,我只說一個,麻煩幫忙解決一下,就是字段里面有from關鍵字,但是不是from,比如fromaddr,這種。

          select fromaddr from abc;

          我試了下解析出來好像是錯的,作者可以試一試。
          另外至于SQL中有常量的情況,常量中包含關鍵字的問題,估計會更加復雜一些;SQL文本中如果存在中文全格的空格作者是否有想過如何解決。

          更復雜的當然是各類SQL的寫法了,尤其是一些方言SQL,但是由于作者只提到簡單SQL我覺得至少是說明單條SQL是可以處理吧;前面兩個問題應該可以考慮下如何避免。  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser[未登錄] 2011-09-15 02:19 aa

          沒有解析子查詢  回復  更多評論   

          # re: 一個利用正則表達式解析單句SQL的類SqlParser[未登錄] 2014-01-20 13:58 Jason

          不錯,解析出來剛好要使用的東西。  回復  更多評論   

          sitinspring(http://www.aygfsteel.com)原創,轉載請注明出處.
          主站蜘蛛池模板: 板桥市| 多伦县| 灌南县| 全椒县| 永吉县| 高雄县| 金华市| 紫金县| 习水县| 全椒县| 安福县| 康乐县| 临安市| 仁化县| 新田县| 梓潼县| 高州市| 黎川县| 恭城| 秦安县| 昭觉县| 建瓯市| 库车县| 蓬溪县| 盱眙县| 剑阁县| 饶河县| 景宁| 淅川县| 永泰县| 黎平县| 通化市| 祁东县| 阿克苏市| 武隆县| 巨鹿县| 巴东县| 林周县| 海原县| 奉贤区| 全椒县|