Oracle 10 和 JDBC:如何让 CHAR 在比较时忽略尾随空格?
Posted
技术标签:
【中文标题】Oracle 10 和 JDBC:如何让 CHAR 在比较时忽略尾随空格?【英文标题】:Oracle10 and JDBC: how to make CHAR ignore trailing spaces at comparision? 【发布时间】:2009-03-02 17:39:28 【问题描述】:我有一个查询
... WHERE PRT_STATUS='ONT' ...
虽然 prt_status 字段被定义为 CHAR(5)。所以它总是用空格填充。查询结果不匹配。为了使这个查询工作,我必须做
... WHERE rtrim(PRT_STATUS)='ONT'
确实有效。
这很烦人。
同时,我的几个纯 Java DBMS 客户端(Oracle SQLDeveloper 和 AquaStudio)在第一次查询时没有问题,它们返回正确的结果。 TOAD 也没有问题。
我认为他们只是将连接置于某种兼容模式(例如 ANSI),因此 Oracle 知道 CHAR(5) 期望在不考虑尾随字符的情况下进行比较。
如何处理我在应用程序中获得的 Connection 对象?
更新我无法更改数据库架构。
解决方案 这确实是 Oracle 比较字段与传入参数的方式。
绑定完成后,字符串通过 PreparedStatement.setString() 传递,它将类型设置为 VARCHAR,因此 Oracle 使用未填充的比较 -- 并且失败。
我尝试使用 setObject(n,str,Types.CHAR)。失败。反编译显示,Oracle 忽略了 CHAR 并再次将其作为 VARCHAR 传入。
最终起作用的变体是
setObject(n,str,OracleTypes.FIXED_CHAR);
但它使代码不可移植。
UI 客户端成功的原因不同——它们使用字符文字,而不是绑定。当我输入 PRT_STATUS='ONT' 时,'ONT' 是一个文字,因此使用填充方式进行比较。
【问题讨论】:
【参考方案1】:注意Oracle compares CHAR
values using blank-padded comparison semantics.
来自Datatype Comparison Rules,
Oracle 使用空白填充比较 语义只有当两个值都在 比较要么是表达式 数据类型 CHAR、NCHAR、文本文字、 或用户返回的值 函数。
在您的示例中,'ONT'
是作为绑定参数传递的,还是如您所说明的那样以文本形式内置到查询中?如果是绑定参数,请确保将其绑定为类型CHAR
。否则,请验证所使用的客户端库版本,因为真正旧版本的 Oracle(例如 v6)对于 CHAR
会有不同的比较语义。
【讨论】:
嗯……这很有道理。 JDBC 的 setString 使用 VARCHAR 来绑定字符串参数。不确定我是否可以用它来解决问题,但至少现在变得更清楚了。 您可能是对的:“只要比较中的一个或两个值的数据类型为 VARCHAR2 或 NVARCHAR2,Oracle 就会使用非填充比较语义”。我需要做一个测试来检查它。 谢谢,弗拉德!请参阅上面的解决方案。 很高兴问题得到解决!五、【参考方案2】:如果你不能改变你的数据库表,你可以修改你的查询。
RTRIM 的一些替代方案:
.. WHERE PRT_STATUS like 'ONT%' ...
.. WHERE PRT_STATUS = 'ONT' ... -- T 后面的 2 个空格
.. WHERE PRT_STATUS = rpad('ONT',5,' ') ...
【讨论】:
【参考方案3】:我会将 CHAR(5) 列更改为 db 中的 varchar2(5)。
【讨论】:
没问题。 DB 不属于我们的组。【参考方案4】:您可以在查询中使用强制转换为字符操作:
... WHERE PRT_STATUS=cast('ONT' as char(5))
或者以更通用的 JDBC 方式:
... WHERE PRT_STATUS=cast(? as char(5))
然后在你的 JDBC 代码中使用statement.setString(1, "ONT");
【讨论】:
以上是关于Oracle 10 和 JDBC:如何让 CHAR 在比较时忽略尾随空格?的主要内容,如果未能解决你的问题,请参考以下文章
oracle decimal(10,0)类型强制转换sql char(10) 如何转换
如何通过 JDBC 将 Java 存储过程加载到 Oracle 10g 中?