遇到一个需求是需要将数据库查询语言中的from后的所有字段全部原样取出,在from前加上select count(*), 如下
" Select a from " + TbItem.class.getName() + " a " + " where a.id= :id"
替换成
“ Select count(*) from " + TbItem.class.getName() + " a " + " where a.id= :id”
或者
"from Employee e where e.name = :name"
替换成
“select cout(*) from Employee e where e.name = :name”
因为有的语句没有select,所以要定位到from前替换
public class AA {
public static void main(String[] args) {
String s=" Select a from xxx a " + " where a.id= :id";
String regex = ".*(from.*)$";
String result=s.replaceAll(regex,"select count(*) $1");
System.out.println(result);
}
}
其他网友的答案
提供一种解决思路:获取sql字符串,根据from分割 str.split("from") 得到 “” 或者 “select XXX ”;
根本不需要判断了,直接全部替换就可以了
楼主采纳的答案其实是有问题的,wchen88 提供的正则表达式".*(from.*)$"考虑的并不全面,在贪婪模式下,'.'字符会匹配from这四个字符前的
尽可能多的字符。如果是单查询语句”select * from aa where ......”,这个正则表达式没有问题,会成功替换成"select count(*) from aa where...",
可如果是子查询”select … from aa where id in(select id from bb where …)”,这个正则表达式就有问题了,在贪婪模式下,会被替换成”select count(*) from bb where …)”,显然是有问题的,
所以正确的正则表达式应该设计成匹配from这4个字符前的文本时采用非贪婪模式,
应是:(?:.*?)from(.*)
在C#下,我是这样设计的:
public string formatSql(string _strSql) {
_strSql = "select * from aa where id in(select id from bb)";
string _regExp = @"(?:.*?)from(.*)";
string _strSqlCnt = "select count(*) from ";
string _strFormatSql = "";
MatchCollection _matchs = Regex.Matches(_strSql,_regExp,RegexOptions.IgnoreCase);
foreach (Match match in _matchs) {
GroupCollection _groups = match.Groups;
string _strGroup = _groups[1].Value;
_strFormatSql= _strSqlCnt + _strGroup;
}
return _strFormatSql;
}