8

我有一个查询

... 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' 是一个文字,因此使用填充方式进行比较。

4

4 回答 4

8

请注意,OracleCHAR使用空白填充的比较语义来比较值。

数据类型比较规则

仅当比较中的两个值都是数据类型 CHAR、NCHAR、文本文字的表达式或 USER 函数返回的值时,Oracle 才使用空白填充的比较语义。

在您的示例中,是'ONT'作为绑定参数传递的,还是如您所说明的那样以文本方式内置到查询中?如果是绑定参数,则确保它被绑定为 type CHAR。否则,请验证所使用的客户端库版本,因为 Oracle 的真正旧版本(例如 v6)对于CHAR.

于 2009-03-02T17:55:32.697 回答
1

如果您无法更改您的数据库表,您可以修改您的查询。

RTRIM 的一些替代方案:

.. WHERE PRT_STATUS 像 'ONT%' ...

.. WHERE PRT_STATUS = 'ONT' ... -- T 后面的 2 个空格

.. WHERE PRT_STATUS = rpad('ONT',5,' ') ...

于 2009-03-02T19:19:16.443 回答
0

我会将 CHAR(5) 列更改为 db 中的 varchar2(5)。

于 2009-03-02T17:42:42.400 回答
0

您可以在查询中使用 cast to char 操作:

... WHERE PRT_STATUS=cast('ONT' as char(5))

或者以更通用的 JDBC 方式:

... WHERE PRT_STATUS=cast(? as char(5))

然后在你的 JDBC 代码中使用statement.setString(1, "ONT");

于 2017-11-24T16:42:25.127 回答