我有一个查询

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

有帮助吗?

解决方案

注意 甲骨文比较 CHAR 使用空白填充比较语义的值。

数据类型比较规则,

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");

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top