我有一个
的查询......在哪里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'是一个文字,因此使用填充方式进行比较。
答案 0 :(得分:8)
请注意Oracle compares CHAR
values using blank-padded comparison semantics.
Oracle使用空白填充比较 语义只有当两个值都在 比较是表达的 数据类型CHAR,NCHAR,文本文字, 或者USER返回的值 功能
在您的示例中,'ONT'
是作为绑定参数传递的,还是以文本方式内置到查询中,如图所示?如果是绑定参数,则确保将其绑定为类型CHAR
。否则,请验证使用的客户端库版本,因为Oracle的旧版本(例如v6)将具有CHAR
的不同比较语义。
答案 1 :(得分:1)
如果您无法更改数据库表,则可以修改查询。
RTRIM的一些替代方案:
..在哪里PRT_STATUS喜欢'ONT%'......
.. WHERE PRT_STATUS ='ONT'... - T
后面有2个空格.. WHERE PRT_STATUS = rpad('ONT',5,'')......
答案 2 :(得分:0)
我会在db中将CHAR(5)列更改为varchar2(5)。
答案 3 :(得分:0)
您可以在查询中使用强制转换操作:
... WHERE PRT_STATUS=cast('ONT' as char(5))
或者以更通用的JDBC方式:
... WHERE PRT_STATUS=cast(? as char(5))
然后在您的JDBC代码中使用statement.setString(1, "ONT");