`

解决表达式解析为sql 语句时遇到除0错误的程序

    博客分类:
  • Java
阅读更多
public class ExprssionHandlerImpl implements ExpressionHandler {

	/*
	 * (no Javadoc) <p>Title: handleExpression</p> <p>Description:
	 * 过滤表达式中为0的除数,同时将表达式转化为合法的sql</p>
	 * @param expression
	 * @return
	 * @see
	 * com.reiyen.htz.database.generateview.ExpressionHandler#handleExpression
	 * (java.lang.String)
	 */

	@Override
	public String handleExpression(String expression) {
		String sql = "";
		Set<String> set = dividerFilter(expression);
		// 如果表达式没有除数
		if (set.size() <= 0) {
			sql = expression;
		}
		else {
			StringBuffer result = new StringBuffer();
			Iterator<String> iterator = set.iterator();
			while (iterator.hasNext()) {
				result.append("nullif(" + iterator.next() + ",0)*");
			}
			result.deleteCharAt(result.length() - 1);
			// 不能用case result when null then null else derivedIndex end as
			sql = " case when  " + result.toString()
			                + " is null then null else " + expression
			                + " end as ";
		}
		return sql;
	}

	/**
	 * <p>
	 * Title: dividerFilter
	 * </p>
	 * <p>
	 * Description: 过滤表达式中的除号"/",得到所有的除数集合
	 * </p>
	 * 
	 * @param expression
	 * @return
	 */
	private Set<String> dividerFilter(String expression) {
		// 去掉原始字符串一个或多个空格
		expression = expression.replaceAll("\\s+", "");
		int index = -1;
		Comparator<String> comparator = new MyComparator();
		// 利用treeSet将长度短的除数排到前面来先判断,如:表达戒a\(b+c\d),则将除数b移到前除数b+c\d前面来,防止出现除数为0的情况出现
		Set<String> dividers = new TreeSet<String>(comparator);
		// 循环检查除号进行过滤,直到检查到过滤后的表达式中没有除号'/',同时使用index将除号的位置标记
		while ((index = expression.indexOf("/", index + 1)) > 0) {
			// 如果除号后面紧跟的是左括号'(',即除数是一个有括号包围的表达式,如:/()。'('这是除数的起点
			if (expression.charAt(index + 1) == '(') {
				// 将位置标记点移动到左括号'('后面的字符上,
				int next = index + 2;
				// 用一个计数器来记录(的数目
				int count = 1;
				// 循环检查括号,检查到左括号'('计数器就加1,如果检查到左括号')',则计数器就减1
				while (count != 0) {
					if (expression.charAt(next) == '(') {
						count++;
					}
					else if (expression.charAt(next) == ')') {
						count--;
					}
					next++;
				}
				// 得到第一表达式中第一层的除数
				String divider = expression.substring(index + 1, next);
				// 使用递归逐层得到除数
				int index1 = divider.indexOf("/", 0);
				if (index1 > 0) {
					Set<String> set = dividerFilter(divider);
					dividers.addAll(set);
				}
				dividers.add(divider);
			}
			else {
				// 除数中没有括号'()',但可能有右括号,如:表达戒a\(b+c\d)中的d);所以要判断右括号')'的情况
				int next = index + 1;
				do {
					char c = expression.charAt(next);
					if (c == '+' || c == '-' || c == '*' || c == '/'
					                || c == ')')
						break;
					else
						next++;
				} while (next < expression.length());
				dividers.add(expression.substring(index + 1, next));
			}
		}
		return dividers;
	}

	public static void main(String args[]) {
		ExpressionHandler handler = new ExprssionHandlerImpl();
		String expression = "a/b + (c/d + f/(d+e))/f + g/p";
		String result = handler.handleExpression(expression);
		System.out.println(result);
	}

}

 比较器:

public class MyComparator implements Comparator<String> {

	public int compare(String arg0, String arg1) {

		int result = 0;
		int len1 = arg0.length();
		int len2 = arg1.length();
		if (len1 < len2) {
			result = -1;
		}
		else if (len1 > len2) {
			result = 1;
		}
		else if (len1 == len2) {
			if (arg0.equals(arg1)) {
				result = 0;
			}
			else {
				result = arg0.compareTo(arg1);
			}
		}
		return result;
	}
}

 比如表达式:"a/b + (c/d + f/(d+e))/f + g/p"

使用此程序解析后输出的sql如下所示:

case when  nullif(b,0)*nullif(d,0)*nullif(f,0)*nullif(p,0)*nullif((d+e),0) is null then null else a/b + (c/d + f/(d+e))/f + g/p end as
 

 

分享到:
评论
2 楼 ryxxlong 2011-12-02  
lhp__2006 写道
帮我解决了一个大问题,多谢

呵呵,就是把平时开发遇到的东西放上来,能帮到人我最开心了
1 楼 lhp__2006 2011-12-02  
帮我解决了一个大问题,多谢

相关推荐

    ambda表达式转SQL语句

    Lambda表达式转SQL语句类库 一、可以达到的功能 本功能类库主要提供给代码中使用Lambda表达式,后需转成SQL的条件语句这一需求 二、不能做的 1、本类库不能解析Linq语句 2、不能解析SQL中的Select部分

    SQL 语法分析,正则表达式解析C#文件;正则表达式实现的语法分析引擎

    一些资料关于 SQL 语法分析;用正则表达式解析C#文件;使用正则表达式实现的语法分析引擎(C#源代码) ;SQL Server 2005正则表达式使模式匹配和数据提取变得更容易;

    Lambda表达式转SQL语句类库

    Lambda表达式转SQL语句类库 一、可以达到的功能 本功能类库主要提供给代码中使用Lambda表达式,后需转成SQL的条件语句这一需求 二、不能做的 1、本类库不能解析Linq语句 2、不能解析SQL中的Select部分

    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 ...

    DBMS.zip_C++_boost实现解析sql语句

    使用boost正则表达式实现c++解析sql语句,仅实现了insert/update/delete.

    sql-protobuf:将SQL CREATE TABLE语句转换为protobuf模式

    使用正则表达式解析SQL被称为“几乎不可能”-但我想我们可以涵盖90%以上的情况。 可能有错误。 如果此命令无法正常运行SQL CREATE TABLE语句,请尝试对其进行修复。 $ npm install -g sql-protobuf 是的,这可以...

    根据MyBatis或iBatis的SQLMapper文件反向生成数据库表

    解析SQL语句: 对于每一条SQL语句,需要解析其中的表名、字段名、数据类型、约束条件等信息。这可以通过正则表达式或者专门的SQL解析器来实现。 生成数据库表结构: 根据解析得到的SQL语句中的表名、字段名、数据类型...

    QT 4.5 多开发语言内嵌SQL语句效率分析

    分析大型系统源代码中包含的SQL语句,解析这些SQL语句访问的数据表和条件表达式,连接数据库,探测对应的数据表包含的记录个数和参与条件过滤的字段的有效值个数,为数据表构建索引策略提供,并自动生成索引创建脚本...

    JS、replace利用正则表达式替换SQL所有参数为指定格式的数据

    SQL参数格式 例如:select * from tb where nd=:nd and yd=:yd 想一次性把所有SQL语句中参数(带冒号)全部换成数据, 开始 选定用正则表达式。 原先写这样 代码如下: strsql.replace(/(:\w+)/g,(“$1”).substring(1)...

    解析Microsoft Sql Server中的like语句

    当使用LIKE进行字符串比较时,模式字符串中的所有字符都有意义,包括起始或尾随空格。如果查询中的比较要返回包含\\\"abc \\\"(abc后有一个空格)的所有行,则将不会返回包含\\\"abc\\\"(abc后没有空格)的列所...

    LINQPad 6.9.15 Premium

    linq语句是编程项目中常常用到的语句,与一般的SQL语句不同,linq语句无法再不运行程序的情况下验证编写语句的正确性,而这款linqpad 就可以完美帮助我们解决这个问题,它支持将linq语句LINQ表达式转换为可用的...

    SQLServer数据脚本转为达梦数据脚本.doc

    此文档主要是将SQLServer数据脚本转为达梦数据库数据脚本,截图为主,有需要的可以参考!

    全国省、市、区、乡镇/街道地址SQL

    建表SQL DROP TABLE IF EXISTS `area`; CREATE TABLE `area` ( `id` int(11) unsigned NOT NULL AUTO_INCREMENT, `parent_id` int(11) NOT NULL COMMENT '父级', `name` varchar(50) NOT NULL DEFAULT '' COMMENT...

    从SQL脚本抽取数据库表名小工具.zip

    从SQL脚本抽取数据库表名的Python小工具。利用正则表达式实现了从复杂的SQL脚本中抽取出使用的数据库实体表名。

    达梦数据库典型语句例子

    达梦数据库典型语句例子,适合新手参考,语法和部分函数略有差异

    达梦数据库sql语言使用手册

    达梦数据库sql语言手册,达梦数据库是国产数据库里最好使用的,可以跟oracle数据无缝替换的

    SQL 优化原则

    ORACLE在内部执行了许多工作: 解析SQL语句, 估算索引的利用率, 绑定变量 , 读数据块等; (5) 在SQL*Plus , SQL*Forms和Pro*C中重新设置ARRAYSIZE参数, 可以增加每次数据库访问的检索数据量 ,建议值为200 (6) ...

    ZQL:Zql是用Java编写SQL解析器。 Zql解析SQL并填写表示SQL语句和表达式的Java结构

    如果您想做出贡献,请确保每次您提交新内容时,最新的CI版本仍在起作用。 ###用法待定 ###问题 可以在GitHub问题跟踪器上找到任何已知问题。 随时添加更多的问题,并提供尽可能多的信息,以便更轻松地重现这些问题...

    PHP-SQL-Parser:纯PHP SQL(非验证)解析器专注于SQLMySQL方言

    PHP-SQL解析器专注于SQLMySQL方言的纯PHP SQL(非验证)解析器下载对以下语句类型MySQL方言的完全支持SELECTINSERTUPDATEDELETEREPLACERENAMESHOWSETDROPCREATE INDEXCREATE TABLEEXPLAINDESCRIBE其他SQL语句类型...

    C#代码段编辑器.zip

    linq语句是编程项目中常常用到的语句,与一般的SQL语句不同,linq语句无法再不运行程序的情况下验证编写语句的正确性,而这款软件就可以完美帮助我们解决这个问题,它支持将linq语句LINQ表达式转换为可用的Lambda...

Global site tag (gtag.js) - Google Analytics