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如何按日期分组,底下的代码如何让它成功?

oracle decimal(10,0)类型强制转换sql char(10) 如何转换

如何通过 JDBC 将 Java 存储过程加载到 Oracle 10g 中?

如何在 java 中使用 jdbc 为 oracle 10g 执行 log miner PL/SQL 查询

java 怎么加载oracle驱动

如何在 oracle 11 中使用 JDBC 4 驱动程序?