SqlParser 一个利用正则表达式解析单句SQL的类

先看要解析的样例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);
}
}
}

(0)

相关推荐

  • SqlParser 一个利用正则表达式解析单句SQL的类

    先看要解析的样例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

  • Python利用正则表达式实现计算器算法思路解析

    (1)不使用eval()等系统自带的计算方法 (2)实现四则混合运算.括号优先级解析 思路: 1.字符串预处理,将所有空格去除 2.判断是否存在括号运算,若存在进行第3步,若不存在则直接进入第4步 3.利用正则表达式获取最底层括号内的四则运算表达式 4.将四则运算表达式进行预处理:表达式开头有负数时,在表达式前加上一个0 5.利用re.split().re.findall()方法,通过加减符号,对四则运算进行拆分为乘除运算式和数字,并保留对应的位置下标. 6.利用re.split().re.fi

  • SQL Server中利用正则表达式替换字符串的方法

    建立正则替换函数,利用了OLE对象,以下是函数代码: --如果存在则删除原有函数 IF OBJECT_ID(N'dbo.RegexReplace') IS NOT NULL DROP FUNCTION dbo.RegexReplace GO --开始创建正则替换函数 CREATE FUNCTION dbo.RegexReplace ( @string VARCHAR(MAX), --被替换的字符串 @pattern VARCHAR(255), --替换模板 @replacestr VARCHAR

  • 利用正则表达式判断一个给定的字符是否是回文

    如果给定的字符串是回文,返回true,反之,返回false. 如果一个字符串忽略标点符号.大小写和空格,正着读和反着读一模一样,那么这个字符串就是palindrome(回文). 注意你需要去掉字符串多余的标点符号和空格,然后把字符串转化成小写来验证此字符串是否为回文. 函数参数的值可以为"racecar","RaceCar"和"race CAR". 关键代码: 去掉字符串中的标点符号和空白格.可以用str.replace()+正则表达式匹配. v

  • SQL SERVER数据库服务器CPU不能全部利用原因解析

    目录 背景 1.现象 2.分析 3.解决 4.其它情况 背景 客户凌晨把HIS数据库迁移到配置更高的新服务器,上午业务高峰时应用非常缓慢,严重影响到业务运行. 1.现象 通过SQL专家云实时可视化界面看到大量的绿点,绿点表示会话在等待某项资源,绿点越大说明等待的会话数越多. 进入活动会话列表,发现大量会话的状态为runnable,runnable代表这个会话可以执行,但没有 CPU 可以分配给它,可以理解为正在等待 CPU 这项系统资源. 但是此时服务器的CPU利用率并不高,在30%左右. 从任

  • 利用正则表达式抓取博客园列表数据

    鉴于我在要完成的asp.net MVC 3 仿照博客园企业系统要用到测试数据,我自己输入太累,所以我就抓取了博客园的部分列表数据,还请dudu不要见怪. 在抓取博客园数据的时候采用了正则表达式,所以有不熟悉正则表达式的朋友可以参考相关资料,其实很容易掌握,就是在具体的实例中会花些时间. 现在我就来把我抓取博客园数据的过程叙述一下,如果有朋友有更好的意见,欢迎提出来. 要使用正则表达式抓取数据,首先就要创建一个正则表达式进行匹配,我推荐使用regulator,这个正则表达式工具,我们可以先使用这个

  • C#中如何利用正则表达式判断字符

    废话不多说了,下面代码给大家介绍下利用正则表达式判断字符的方法,具体代码如下所示: using System; using System.Text.RegularExpressions; using System.NET; namespace 正则表达式检测字符串 { class Program { static void Main(string[] args) { Console.WriteLine("请输入字符串:"); string s = Console.ReadLine();

  • Python爬虫教程之利用正则表达式匹配网页内容

    前言 Python爬虫,除了使用大家广为使用的scrapy架构外,还有很多包能够实现一些简单的爬虫,如BeautifulSoup.Urllib.requests,在使用这些包时,有的网络因为比较复杂,比较难以找到自己想要的代码,在这个时候,如果能够使用正则表达式,将能很方便地爬取到自己想要的数据. 何为正则表达式 正则表达式是一种描述字符串排列的一种语法规则,通过该规则可以在一个大字符串中匹配出满足规则的子字符串.简单来说,就是给定了一个字符串,在字符串中找到想要的字符串,如一个电话号码,一个I

  • js利用正则表达式检验输入内容是否为网址

    js正则检验输入的是否为网址功能在网页中也是很常见的,友情链接部分.表单填写个人主页的时候,使用JavaScript取验证是否为网址. 这个检验不好写,最好还是使用正则表达式去认证. 规定,输入的东西只能是http://与https://开头,而且必须是网址. 有人说,为何像www.1.com这样的网页不行呢? 这是以免你拿用户输入的东西构造超级链接的时候,a标签中的href属性如果遇不到http://或者https://的东西,那么就会认为是根目录,会在你的网站的网址后面接着写入这个地址再跳转

  • JavaScript中的正则表达式解析

    JavaScript中的正则表达式解析 正则表达式(regular expression)对象包含一个正则表达式模式(pattern).它具有用正则表达式模式去匹配或代替一个字符串(string)中特定字符(或字符集合)的属性(properties)和方法(methods).要为一个单独的正则表达式添加属性,可以使用正则表达式构造函数(constructor function),无论何时被调用的预设置的正则表达式拥有静态的属性(the predefined RegExp object has s

随机推荐