posts - 30,  comments - 85,  trackbacks - 0

          最近因工作需要寫(xiě)一個(gè)能夠解析任何sql語(yǔ)句。并將該sql語(yǔ)句中涉及到表提取出來(lái)。得到這條sql語(yǔ)句查詢(xún)的都是那幾張表的一個(gè)工具。

          我采用了java正則表達(dá)式來(lái)處理這一需求。 下面是我的代碼。希望大家能夠參考。同時(shí)也提出我可能沒(méi)有想到的復(fù)雜sql是否能夠處理。呵呵! 謝謝!

          package com.ibm.easyoa.sqlparser;

          import java.util.ArrayList;
          import java.util.List;
          import java.util.regex.Matcher;
          import java.util.regex.Pattern;
          /**
           * SQL 解析
           * @author anwenhao
           *
           */
          public class SqlParserEngine {
           
           private static final String TABLE_VALUE = "([^()]+)";

           /**
            * 1. select * from table
            * 2. select * from table where
            * 3. select * from tableA , tableB
            * 4. select * from tableA where * from (select * from tableB)
            * 5. select * from tableA where * from (select * from tableB  where * from (select * from tableC))...
            * 6. select * from tableA union select * from tableB
            * 7. select * from tableA (left/right) join tableB on ...
            *
            * 考慮以上7種情況的SQL parser過(guò)程 這里采用正則表達(dá)式解析
            * @param sql
            * @return
            */
           public List parserSql(String sql){
            List result = new ArrayList();
            String metaRxp = "(?i)select ([^from]+) (?i)from " + TABLE_VALUE;
            Pattern pattern = null;
            Matcher matcher = null;
            pattern = Pattern.compile(metaRxp);
            matcher = pattern.matcher(sql);
            while (matcher.find()) {
             String result1 = matcher.group();
             result1 = this.parserTable(result1, metaRxp);
             //處理是否有where的情況
             String regx = TABLE_VALUE + " (?i)where ([^;]+)";
             Pattern pattern1 = Pattern.compile(regx);
             Matcher matcher1 = pattern1.matcher(result1);
             if (matcher1.find()) {
              String result2 = matcher1.group();
              String tableName = this.parserTable(result2, regx);
              result.addAll(getTableResult(tableName));
             }else{
              // 這里有兩種情況。一種是標(biāo)準(zhǔn)的另一種是join的
              String regx2 = TABLE_VALUE + " (?i)join " + "([^;]+)";
              Pattern pattern2 = Pattern.compile(regx2);
              Matcher matcher2 = pattern2.matcher(result1);
              if (matcher2.find()) {
               String result3 = matcher2.group();
               String table1 = this.parserTable(result3, regx2);
               String table2 = result3.substring(result3.toLowerCase().indexOf("join")+"join".length() , result3.toLowerCase().indexOf("on"));
               result.addAll(getTableResult(table1));
               result.addAll(getTableResult(table2));
              }else{
               result.addAll(getTableResult(result1));
              }
             }
            }
            return result;
           }
           
           /**
            * 將解析出來(lái)的table的表名和別名分別存儲(chǔ)
            * @param table
            * @return
            */
           private List getTableResult(String table){
            List result = new ArrayList();
            String[] tempTable = table.split(",");
            for(int i = 0 ; i < tempTable.length ; i++){
             table = tempTable[i].trim();
             String tableResult[] = new String[2];
             String regx = "([a-zA-Z0-9_]+)([\\s]+)([a-zA-Z0-9_]+)";
             Pattern pattern1 = Pattern.compile(regx);
             Matcher matcher1 = pattern1.matcher(table);
             if (matcher1.find()) {
              String[] temp = table.split("([\\s]+)");
              if(temp.length >= 2){
               tableResult[0] = temp[0];
               tableResult[1] = temp[1];
              }
             }else{
              tableResult[0] = table;
             }
             result.add(tableResult);
            }
            return result;
           }
            
           
           /**
            * 通過(guò)傳入符合規(guī)則的sql語(yǔ)句去得到當(dāng)前sql的table
            * @param sql
            * @param metaRxp
            * @return
            */
           private String parserTable(String sql, String metaRxp) {
            if (null == metaRxp || metaRxp.length() < 2) {
             return "";
            }
            int i = metaRxp.indexOf(TABLE_VALUE);
            if (i != -1) {
             String str1 = metaRxp.substring(0, i);
             String str2 = metaRxp.substring(i + TABLE_VALUE.length());
             String regex = str1 + TABLE_VALUE + str2;
             Pattern pattern = null;
             Matcher matcher = null;
             pattern = Pattern.compile(regex);
             matcher = pattern.matcher(sql);
             while (matcher.find()) {
              String functionMethod = matcher.group();
              if (functionMethod != null) {
               functionMethod = functionMethod.replaceAll(str1, "");
               functionMethod = functionMethod.replaceAll(str2, "");
               return functionMethod;
              }
             }
            }
            return null;
           }
           
           public static void main(String[] args){
            String sql = "select * from tableA aa , tableD dd where * from (select * from tableB  where * from (select * from tableC))";
            SqlParserEngine engine = new SqlParserEngine();
            List tempList = engine.parserSql(sql);
            for(int i = 0 ; i < tempList.size() ; i++){
             String[] result = (String[])tempList.get(i);
             System.out.println("表名 :" + result[0]);
             System.out.println("別名 :" + result[1]);
             System.out.println("==========================================");
            }
           }
           
          }


          posted on 2007-06-25 15:53 安文豪 閱讀(3050) 評(píng)論(10)  編輯  收藏

          FeedBack:
          # re: 解析SQL語(yǔ)句的engine
          2007-06-25 16:18 | 安文豪
          怎么沒(méi)有人回復(fù)呢!請(qǐng)大家?guī)蛶兔Πⅲ?nbsp; 回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2007-06-25 16:54 | narry
          試試看,正需要一個(gè)這樣的工具  回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2007-06-25 18:12 | BeanSoft
          我也試試看.  回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2007-07-10 09:27 | sitinspring
          我也試試看.  回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2007-07-10 14:47 | sitinspring
          select (select sysdate from dual), f01 from table1

          匹配不上啊  回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine[未登錄](méi)
          2008-02-15 09:53 | tiger
          做的不錯(cuò)喲  回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2008-04-29 14:04 | 蔣家狂潮
          不錯(cuò),除了正則表達(dá)式的方法,還有別的方法嗎?不知道 java sql parser 行不?  回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2008-04-29 17:52 | 蔣家狂潮
          我 運(yùn)行過(guò)你的程序,就是 正則表達(dá)式有點(diǎn)問(wèn)題
          String metaRxp = "(?i)select ([^from]+) (?i)from " + TABLE_VALUE;
          加入 sql語(yǔ)句 包含from任一個(gè)字符,查詢(xún)便會(huì)出問(wèn)題:
          譬如:select f from tableA;或者 select r from tableB
          我不是很懂正則表達(dá)式 我覺(jué)得 [^from] 應(yīng)該 匹配 不包含from 字符串的語(yǔ)句,而不是from的其中任意字符。我不知道 “不包含from 字符串 "正則表達(dá)式怎么寫(xiě):)  回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2009-05-07 13:31 | wolfman09
          想問(wèn)下:
          "(?i)select ([^from]+) (?i)from " + TABLE_VALUE;
          這個(gè)正則表達(dá)式里的的(?i)表示什么意思
            回復(fù)  更多評(píng)論
            
          # re: 解析SQL語(yǔ)句的engine
          2009-09-02 10:58 | he
          是啊,對(duì)于后面的group by。order by having , 也沒(méi)有匹配,而且,如果有select name as 'from' from test 做何處理?  回復(fù)  更多評(píng)論
            

          只有注冊(cè)用戶(hù)登錄后才能發(fā)表評(píng)論。


          網(wǎng)站導(dǎo)航:
           

          <2009年9月>
          303112345
          6789101112
          13141516171819
          20212223242526
          27282930123
          45678910

          常用鏈接

          留言簿(6)

          隨筆檔案(28)

          文章分類(lèi)(3)

          文章檔案(4)

          最新隨筆

          搜索

          •  

          積分與排名

          • 積分 - 86627
          • 排名 - 668

          最新評(píng)論

          閱讀排行榜

          評(píng)論排行榜

          主站蜘蛛池模板: 固原市| 福州市| 乌什县| 台山市| 丰原市| 明溪县| 姜堰市| 广汉市| 庆元县| 大宁县| 清苑县| 杭锦后旗| 临洮县| 西乌| 黔东| 麦盖提县| 基隆市| 榆树市| 锡林郭勒盟| 屏南县| 鞍山市| 三都| 克什克腾旗| 调兵山市| 隆林| 安宁市| 新田县| 平原县| 顺义区| 洞口县| 广安市| 阿拉善右旗| 岳阳市| 浪卡子县| 泸溪县| 辉南县| 穆棱市| 福安市| 永丰县| 上林县| 井冈山市|