posts - 30,  comments - 85,  trackbacks - 0

最近因工作需要写一个能够解析任何sql语句。并将该sql语句中涉及到表提取出来。得到这条sql语句查询的都是那几张表的一个工具。

我采用了java正则表达式来处理这一需求。 下面是我的代码。希望大家能够参考。同时也提出我可能没有想到的复杂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过程 这里采用正则表达式解析
  * @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{
    // 这里有两种情况。一种是标准的另一种是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;
 }
 
 /**
  * 将解析出来的table的表名和别名分别存储
  * @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;
 }
  
 
 /**
  * 通过传入符合规则的sql语句去得到当前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 安文豪 阅读(3032) 评论(10)  编辑  收藏

FeedBack:
# re: 解析SQL语句的engine
2007-06-25 16:18 | 安文豪
怎么没有人回复呢!请大家帮帮忙阿!  回复  更多评论
  
# re: 解析SQL语句的engine
2007-06-25 16:54 | narry
试试看,正需要一个这样的工具  回复  更多评论
  
# re: 解析SQL语句的engine
2007-06-25 18:12 | BeanSoft
我也试试看.  回复  更多评论
  
# re: 解析SQL语句的engine
2007-07-10 09:27 | sitinspring
我也试试看.  回复  更多评论
  
# re: 解析SQL语句的engine
2007-07-10 14:47 | sitinspring
select (select sysdate from dual), f01 from table1

匹配不上啊  回复  更多评论
  
# re: 解析SQL语句的engine[未登录]
2008-02-15 09:53 | tiger
做的不错哟  回复  更多评论
  
# re: 解析SQL语句的engine
2008-04-29 14:04 | 蒋家狂潮
不错,除了正则表达式的方法,还有别的方法吗?不知道 java sql parser 行不?  回复  更多评论
  
# re: 解析SQL语句的engine
2008-04-29 17:52 | 蒋家狂潮
我 运行过你的程序,就是 正则表达式有点问题
String metaRxp = "(?i)select ([^from]+) (?i)from " + TABLE_VALUE;
加入 sql语句 包含from任一个字符,查询便会出问题:
譬如:select f from tableA;或者 select r from tableB
我不是很懂正则表达式 我觉得 [^from] 应该 匹配 不包含from 字符串的语句,而不是from的其中任意字符。我不知道 “不包含from 字符串 "正则表达式怎么写:)  回复  更多评论
  
# re: 解析SQL语句的engine
2009-05-07 13:31 | wolfman09
想问下:
"(?i)select ([^from]+) (?i)from " + TABLE_VALUE;
这个正则表达式里的的(?i)表示什么意思
  回复  更多评论
  
# re: 解析SQL语句的engine
2009-09-02 10:58 | he
是啊,对于后面的group by。order by having , 也没有匹配,而且,如果有select name as 'from' from test 做何处理?  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航:
 

<2007年6月>
272829303112
3456789
10111213141516
17181920212223
24252627282930
1234567

常用链接

留言簿(6)

随笔档案(28)

文章分类(3)

文章档案(4)

最新随笔

搜索

  •  

积分与排名

  • 积分 - 85913
  • 排名 - 663

最新评论

阅读排行榜

评论排行榜