请问怎样分析一个sql语句查询了哪几张表。
例如,有下边几种情况
select * from ta tb
select * from ta as tb
select ta.*,tb.* from ta,tb,tc where xxx=xxx
select ta.*,tb.* from ta t1,tb t2,tc t3 where
select ta.*,tb.* from ta join tb on xxx join tc
select ta.*,tb.* from ta t1 join tb t2 on xxx join tc t3 on xxxxx 有什么好的算法分析这些语句,可以得到查询的物理表。
随便给个思路 或者伪代码都行,分不够再加。谢谢!
例如,有下边几种情况
select * from ta tb
select * from ta as tb
select ta.*,tb.* from ta,tb,tc where xxx=xxx
select ta.*,tb.* from ta t1,tb t2,tc t3 where
select ta.*,tb.* from ta join tb on xxx join tc
select ta.*,tb.* from ta t1 join tb t2 on xxx join tc t3 on xxxxx 有什么好的算法分析这些语句,可以得到查询的物理表。
随便给个思路 或者伪代码都行,分不够再加。谢谢!
大致思路,不一定完整。
import java.util.*;public class testSQL { public static void main(String[] args) {
String sql = "select ta.*,tb.* from ta t1 join tb t2 on xxx join tc t3 on xxxxx ";
ArrayList list = new ArrayList();
int indexOfWhere;
int indexOfFrom;
sql = sql.replaceAll("join", ",");
if (sql.indexOf("where") != -1) {
indexOfWhere = sql.indexOf("where");
} else {
indexOfWhere = sql.length();
}
indexOfFrom = sql.indexOf("from");
sql = sql.substring(indexOfFrom + 4, indexOfWhere);
StringTokenizer st = new StringTokenizer(sql, ",") ;
while(st.hasMoreElements()) {
String temp = st.nextToken().trim();
list.add(temp.substring(0,temp.indexOf(" ")).trim());
} for(Iterator iter = list.iterator(); iter.hasNext();) {
System.out.println((String)iter.next());
}
}}
SELECT语句的EBNF表达式可以在SQL Server或者Oracle的帮助文档里找到,然后构造词汇表,词法分析,造语法树,就可以了分析了。这样最准确,但是会比较麻烦,建议你用已经写好的第三方工具类库,比如antlr。你可以查一下antlr的用法。Hibernate在分析HQL转成SQL的过程就是用的antlr, WebLogic把EJB QL转SQL也使用的这个类库。如果你的SQL只包含你的例子中那几种情况,那么或许可以简单的处理,自己写一个词法分析器,parse过程中你可以把FROM后面和JOIN后面的处理一下。这样扩展性差,只适用于比较简单的。总之无论如何,此法分析器一定要写的,不能直接String.indexof("FROM")或者String.indexof("JOIN"),比如这种情况:
SELECT 'It''s a Message from the ' + address from contact
你必须用词法分析器把这个SQL解释为
SELECT:关键字
'It''s a Message from the ':literal
+:运算符
address:标识符
from:关键字
contact:标识符然后你才能根据EBNF语法定义找语法树中关键字from后面的标识符作为表名
如果对于这个SQL你直接用String.indexof("FROM"),那么第一个from后面是the,这就毫无道理的乱套了
String.replace("JOIN", ",")
String.indexOf("FROM")
String.indexOf("JOIN")
用正则表达式就可以
例如:
select ta.*,tb.* from ta,tb,tc where xxx=xxx String s="select ta.*,tb.* from ta,tb,tc where sdfdsf sdafsd xxx=xxx";
Pattern p = Pattern.compile("from\\s+([^\\s]+)\\s"); Matcher m = p.matcher(s); boolean rs=m.find();
for (int i = 1; i <= m.groupCount(); i++) {
System.out.println(m.group(i));
}
得出结果:ta,tb,tc ,然后再对结果以,区分出各个表
当然如果SQL中还有join就比较麻烦了,但是同样写出正则表达式,再过滤一次就可以了
SELECT 'It''s a Message from the ' + address from contact
按你给的正则表达式
from\\s+([^\\s]+)\\s
来匹配,明显结果是错误的还有很多其他的情况,也会出错,就不一一列举了