Oracle10 和 JDBC:如何使 CHAR 在比较时忽略尾随空格?
题
我有一个查询
...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' 是一个文字,因此使用填充方式进行比较。
解决方案
从 数据类型比较规则,
Oracle仅当比较中的两个值都是DataType char,nchar,文本文字或用户函数返回的值的表达式时,才会使用空白的比较语义。
在你的例子中,是 'ONT'
作为绑定参数传递,还是以文本方式内置到查询中,如您所示?如果是绑定参数,请确保它被绑定为类型 CHAR
. 。否则,验证使用的客户端库版本,作为 Oracle 的真正旧版本(例如v6) 将具有不同的比较语义 CHAR
.
其他提示
如果您无法更改数据库表,则可以修改查询。
RTRIM 的一些替代方案:
..WHERE PRT_STATUS 如“ONT%”...
..WHERE PRT_STATUS = 'ONT' ...-- T 后面有 2 个空格
..其中 PRT_STATUS = rpad('ONT',5,' ') ...
我会将 db 中的 CHAR(5) 列更改为 varchar2(5)。
您可以在查询中使用强制转换为字符操作:
... WHERE PRT_STATUS=cast('ONT' as char(5))
或者以更通用的 JDBC 方式:
... WHERE PRT_STATUS=cast(? as char(5))
然后在你的 JDBC 代码中使用 statement.setString(1, "ONT");