我对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
数据类型的好习惯是什么?
答案 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() 添加到更新查询中的列名(已定义)即可。