C++ 使用oci访问数据库出现“Column: 2<DOUBLE>, datatype in operator <</>>: CHAR”

本文讨论了在VC环境下处理Oracle数据库中number类型字段的挑战,包括使用int、long int、string、otl_stream等数据类型进行读取的方法与常见错误,并提供了解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

http://bbs.youkuaiyun.com/topics/90049666


比如有表a,其中一个字段是number类型的,如果在vc中读取这个大数,用什么来读取?
vc中int 和long int都是4个字节的,根本不够用啊?
如果定义一个string s来接受这个整数的话,用otl_stream o;
o>>s;接受的时候,提示错误,因为oracle里面的number不能用string来接受,如果用int i;
o>>i;可以,但是i溢出,得到的值不正确啊,谁遇到过这样的情况,怎么解决的?


不能用char来接收number字段的内容
提示错误如下:
Column: 1<DOUBLE>, datatype in operator <</>>: CHAR


otl_long_string 只能接收oracle数据库中字段为long类型的,number类型的不能用otl_long_string来接收,如果用otl_long_string来接收的话,例如

otl_long_sring ols;
o>>ols; // o 为 otl_stream 类型
提示出错,类似和用char接收number一样的错误,


不是说了嘛
ostream::set_column_type转成字符串
读出来后,
boost::lexical_cast或者自己处理字符串都可以
哎……

private static Expression getExpression(FilterItem filterItem, HeaderItem headerItem) { String operator = filterItem.getOperator(); String column = filterItem.getColumn(); String value = filterItem.getValue(); Expression exp = null; if (headerItem == null) { headerItem = new HeaderItem(); } value = value.replaceAll(",", ","); if ("between".equals(operator)) { Between between = new Between(); String[] split = value.split(","); between.setLeftExpression(new Column(column)); if (SystemConstants.DATA_TYPE_DATE17.equals(headerItem.getDataType())) { between.setBetweenExpressionStart(new DateValue(Date.valueOf(split[0]))); between.setBetweenExpressionEnd(new DateValue(Date.valueOf(DateUtils.plusDayByString(split[1], 1)))); } else if (SystemConstants.DATA_TYPE_DATE6.equals(headerItem.getDataType())) { between.setBetweenExpressionStart(new DateValue(Date.valueOf(split[0]))); between.setBetweenExpressionEnd(new DateValue(Date.valueOf(split[1]))); } else { between.setBetweenExpressionStart(new StringValue(split[0])); between.setBetweenExpressionEnd(new StringValue(split[1])); } exp = between; } else if ("%like%".contains(operator)) { String[] split = value.split(","); List<Expression> orList = new ArrayList<>(); for (String keyword : split) { orList.add(getExpression(operator, column, headerItem.getDataType(), keyword, exp)); } exp = new ChainOrExpression(orList); } else if ("in not in".contains(operator)) { String[] split = value.split(","); List<Expression> valList = new ArrayList<>(); for (String keyword : split) { valList.add(new StringValue(keyword)); } InExpression inExpression = new InExpression(); if ("not in".equals(operator)) { inExpression.setNot(true); } inExpression.setLeftExpression(new Column(column)); ExpressionList expressionList = new ExpressionList(); expressionList.setExpressions(valList); inExpression.setRightExpression(expressionList); exp = inExpression; } else { exp = getExpression(operator, column, headerItem.getDataType(), value, exp); } return exp; } inExpression.setRightExpression(expressionList); jsqlparser5.3版本没加括号,导致系统报错
最新发布
07-13
<think>我们正在使用JSqlParser 5.3版本,用户遇到了`inExpression.setRightExpression(expressionList)`未加括号导致SQL语法错误的问题。 在JSqlParser中,当我们构建一个IN表达式时,IN后面的列表应该是一个括号包围的表达式列表。但是直接使用`setRightExpression`设置一个`ExpressionList`并不会自动添加括号,这会导致生成的SQL语句缺少括号,从而出现语法错误。 解决方案: 在JSqlParser中,`InExpression`有两个设置右边表达式的方法: 1. `setRightExpression(Expression expression)`:这个方法用于设置一个表达式,但是不会自动添加括号。如果我们传入一个`ExpressionList`,那么生成的SQL就会是`column IN value1, value2`,这是错误的,因为正确的应该是`column IN (value1, value2)`。 2. `setRightItemsList(ItemsList itemsList)`:这个方法专门用于设置IN后面的列表,它接受一个`ItemsList`对象,而`ExpressionList`就是`ItemsList`的一个实现。当我们使用这个方法时,它会自动在生成SQL时添加括号。 因此,正确的做法是使用`setRightItemsList`方法,并将`ExpressionList`传递给它。 修改代码示例: 原代码: inExpression.setRightExpression(expressionList); 修改为: inExpression.setRightItemsList(expressionList); 这样生成的SQL就会是`column IN (value1, value2)`。 另外,对于`NOT IN`,同样使用`setRightItemsList`方法。 因此,针对用户提供的代码段,我们应该修改IN表达式和NOT IN表达式的构建部分: 原代码片段: InExpression inExpression = new InExpression(); if ("not in".equals(operator)) { inExpression.setNot(true); } inExpression.setLeftExpression(new Column(column)); ExpressionList expressionList = new ExpressionList(); expressionList.setExpressions(valList); inExpression.setRightExpression(expressionList); // 这里导致问题 修改为: InExpression inExpression = new InExpression(); if ("not in".equals(operator)) { inExpression.setNot(true); } inExpression.setLeftExpression(new Column(column)); ExpressionList expressionList = new ExpressionList(valList); // 可以直接在构造时传入 inExpression.setRightItemsList(expressionList); // 使用正确的方法 注意:`ExpressionList`的构造方法可以接受一个表达式列表,所以我们可以直接`new ExpressionList(valList)`。 另外,在JSqlParser 5.3中,`ExpressionList`的构造方法有多种,我们也可以使用无参构造然后调用`setExpressions`。 这样修改后,生成的SQL就会正确包含括号。 同时,我们注意到在代码中还有处理`between`和`like`的部分,但当前问题只涉及IN表达式。 因此,我们只需要修改IN表达式部分的代码即可。 如果用户使用的是较旧版本的JSqlParser(如1.0),那么可能没有`setRightItemsList`方法,但根据引用[1]的提示,用户已经使用了5.3版本,所以应该支持这个方法。 另外,引用[2]和引用[3]提到了JSqlParser的解析能力,说明它能够处理复杂的SQL,包括IN和子查询等。因此,使用正确的方法构建表达式非常重要。 总结:将`setRightExpression`替换为`setRightItemsList`,并确保传递的是`ItemsList`类型(`ExpressionList`是其子类),这样就会自动生成括号。 修改后的代码片段如下: ```java } else if ("in not in".contains(operator)) { String[] split = value.split(","); List<Expression> valList = new ArrayList<>(); for (String keyword : split) { valList.add(new StringValue(keyword)); } InExpression inExpression = new InExpression(); if ("not in".equals(operator)) { inExpression.setNot(true); } inExpression.setLeftExpression(new Column(column)); ExpressionList expressionList = new ExpressionList(valList); inExpression.setRightItemsList(expressionList); // 修改这里 exp = inExpression; ``` 这样修改后,生成的IN表达式就会带有括号,避免语法错误。 如果用户需要处理更复杂的情况,比如子查询作为IN的右表达式,那么应该构建一个`SubSelect`对象,并用`ParenthesedExpression`包裹(或者直接使用`SubSelect`,它本身在生成SQL时会带括号),然后使用`setRightExpression`方法(因为子查询本身就是括号包围的)。但是当前场景是值列表,所以使用`setRightItemsList`是最合适的。 因此,我们只需要修改这一处即可解决问题。</think># 解决 JSqlParser 5.3 中 InExpression 缺少括号问题 在 JSqlParser 5.3 版本中,`inExpression.setRightExpression(expressionList)` 未加括号会导致 SQL 语法错误。这是因为 SQL 语法要求 IN/NOT IN 子句的值列表必须用括号包裹。 ## 问题原因分析 在 JSqlParser 中: - `InExpression` 的右表达式必须是一个 `ItemsList` 类型 - 直接使用 `setRightExpression()` 设置 `ExpressionList` 不会自动添加括号 - 这会导致生成的 SQL 缺少括号,如 `id IN 1,2,3` 而不是正确的 `id IN (1,2,3)` ## 完整解决方案 ### 正确构建 IN 表达式的方法 ```java // 创建 IN 表达式 InExpression inExpression = new InExpression(); // 设置左表达式(列名) inExpression.setLeftExpression(new Column(column)); // 创建值列表 List<Expression> valList = new ArrayList<>(); for (String keyword : split) { valList.add(new StringValue(keyword)); } // 正确方法:使用 ItemsList 接口 ExpressionList expressionList = new ExpressionList(); expressionList.setExpressions(valList); // 关键修复:使用 setRightItemsList() 而不是 setRightExpression() inExpression.setRightItemsList(expressionList); // ✅ 正确方法 // 错误方法:会导致缺少括号 // inExpression.setRightExpression(expressionList); // ❌ 会导致语法错误 ``` ### 完整修改后的代码片段 ```java } else if ("in not in".contains(operator)) { String[] split = value.split(","); List<Expression> valList = new ArrayList<>(); for (String keyword : split) { valList.add(new StringValue(keyword)); } InExpression inExpression = new InExpression(); if ("not in".equals(operator)) { inExpression.setNot(true); } inExpression.setLeftExpression(new Column(column)); // 修复:正确使用 ItemsList ExpressionList expressionList = new ExpressionList(valList); inExpression.setRightItemsList(expressionList); // ✅ 正确方法 exp = inExpression; ``` ## 版本兼容性说明 JSqlParser 5.3 中: - `setRightItemsList()` 方法是正确处理值列表的正确方式 - 该方法会自动为值列表添加括号 - 使用旧版本(如 1.0)时,需要确保导入正确的 jar 包[^1] ## 其他注意事项 1. **子查询处理**:当 IN 子句包含子查询时,应使用 `ParenthesedExpression` 包裹: ```java SubSelect subSelect = new SubSelect(selectBody); inExpression.setRightExpression(new ParenthesedExpression(subSelect)); ``` 2. **复杂表达式**:对于包含多个条件的 WHERE 子句,使用 `AndExpression` 或 `OrExpression` 组合[^3]: ```java Expression where = new AndExpression( new GreaterThan(column1, value1), new OrExpression( new EqualsTo(column2, value2), new NotEqualsTo(column3, value3) ) ); ``` 3. **SQL 格式保持**:使用 `CCJSqlParserUtil` 解析和重新格式化 SQL 可保持格式正确: ```java Statement statement = CCJSqlParserUtil.parse("SELECT * FROM table"); String formattedSql = statement.toString(); // 格式正确的SQL ``` ## 常见错误排查 如果遇到类找不到错误: 1. 确保使用正确的依赖版本: ```xml <dependency> <groupId>com.github.jsqlparser</groupId> <artifactId>jsqlparser</artifactId> <version>5.3</version> </dependency> ``` 2. 检查导入的类路径: ```java import net.sf.jsqlparser.expression.Expression; import net.sf.jsqlparser.expression.operators.relational.ExpressionList; import net.sf.jsqlparser.expression.operators.relational.InExpression; ``` 通过使用 `setRightItemsList()` 替代 `setRightExpression()`,可以彻底解决 IN 表达式缺少括号的问题,确保生成的 SQL 语法正确[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值