Oracle JDBC和Oracle CHAR数据类型

时间:2011-03-16 22:59:29

标签: oracle jdbc types char prepared-statement

我对Oracle JDBC驱动程序处理CHAR数据类型有一个棘手的问题。我们来看看这个简单的表格:

create table x (c char(4));
insert into x (c) values ('a');  -- inserts 'a   '

因此,当我在CHAR(4)中插入内容时,字符串始终用空格填充。当我执行这样的查询时也会这样做:

select * from x where c = 'a';    -- selects 1 record
select * from x where c = 'a ';   -- selects 1 record
select * from x where c = 'a   '; -- selects 1 record

此处,常量'a'也填充了空格。这就是记录总是返回的原因。当使用JDBC PreparedStatement执行这些查询时,这也适用。现在最棘手的是当我想使用绑定变量时:

PreparedStatement stmt = 
  conn.prepareStatement("select * from x where c = ?");
stmt.setString(1, "a");    // This won't return any records
stmt.setString(1, "a   "); // This will return a record
stmt.executeQuery();

这是一种解决方法:

PreparedStatement stmt = 
  conn.prepareStatement("select * from x where trim(c) = trim(?)");
stmt.setString(1, "a");    // This will return a record
stmt.setString(1, "a   "); // This will return a record
stmt.executeQuery();

编辑:现在这些是限制因素:

  • 上述解决方法不是必需的,因为它修改了c?的内容,并且它使c上的索引非常难用。
  • 将列从CHAR移至VARCHAR(当然应该是这样)

编辑:这些限制的原因是因为我从数据库抽象库jOOQ的开发人员的角度提出这个问题。所以我的要求是提供一个非常通用的解决方案,它不会破坏jOOQ客户端代码中的任何内容。这就是为什么我不是真正的解决方法的忠实粉丝。这就是为什么我无法访问CHAR列的声明。但是,我仍然希望能够处理这种情况。

你会做什么?当我想忽略尾随空格时,处理CHAR数据类型的好习惯是什么?

6 个答案:

答案 0 :(得分:11)

如果你想要

stmt.setString(1, "a");    // This won't return any records

要返回记录,请尝试

conn.prepareStatement("select * from x where c = cast(? as char(4))")

答案 1 :(得分:2)

即使它是Oracle中的char(1),我也没有看到任何使用CHAR数据类型的理由。你能改变数据类型吗?

答案 2 :(得分:1)

加里的解决方案效果很好。这是另一种选择。

如果您使用的是Oracle JDBC驱动程序,则对prepareStatement()的调用实际上将返回OraclePreparedStatement,其setFixedCHAR()方法会自动使用空格填充您的输入。

String sql = "select * from x where c = ?";
OraclePreparedStatement stmt = (OraclePreparedStatement) conn.prepareStatement(sql);
stmt.setFixedCHAR(1, "a");
...

显然,如果你使用的是Oracle驱动程序,那么强制转换是安全的。

我建议您使用这个而不是Gary的答案的唯一原因是您可以更改列大小而无需修改JDBC代码。驱动程序填充正确数量的空间,而开发人员无需知道/管理列大小。

答案 3 :(得分:0)

我对此有很好的解决方法。您必须在从数据库获取连接时添加一个属性。

NLS_LANG=american_america.AL32UTF8

或在Java连接中,您可以使用以下代码:

java.util.Properties info = new java.util.Properties();
info.put ("user", user);
info.put ("password",password);
info.put("fixedString","TRUE");
info.put("NLS_LANG","american_america.AL32UTF8");
info.put("SetBigStringTryClob","TRUE");
String url="jdbc:oracle:thin:@"+serverName;
log.debug("url="+url);
log.debug("info="+info);
Class.forName("oracle.jdbc.OracleDriver");
conn  = DriverManager.getConnection(url,info);

答案 4 :(得分:0)

另一种方法是将sql修改为

select * from x where NVL(TRIM(c),' ') = NVL(TRIM('a'),' ')

答案 5 :(得分:0)

只需将 RTRIM() 添加到更新查询中的列名(已定义)即可。