Oracle JDBC 和 Oracle CHAR 数据类型
我在 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 数据类型的好习惯是什么?
I have a tricky issue with the Oracle JDBC driver's handling of CHAR
data types. Let's take this simple table:
create table x (c char(4));
insert into x (c) values ('a'); -- inserts 'a '
So when I insert something into CHAR(4)
, the string is always filled with whitespace. This is also done when I execute queries like this:
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
Here, the constant 'a'
is filled with whitespace as well. That's why the record is always returned. This holds true when these queries are executed using a JDBC PreparedStatement
as well. Now the tricky thing is when I want to use a bind variable:
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();
This is a workaround:
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();
EDIT: Now these are the constraints:
- The above workaround is not desireable as it modifies both the contents of
c
and?
, AND it makes using indexes onc
quite hard. - Moving the column from
CHAR
toVARCHAR
(which it should be, of course) is not possible
EDIT: The reasons for these constraints is because I ask this question from the point of view of the developer of jOOQ, a database abstraction library. So my requirements are to provide a very generic solution that doesn't break anything in jOOQ's client code. That is why I'm not really a big fan of the workaround. And that's why I don't have access to that CHAR
column's declaration. But still, I want to be able to handle this case.
What would you do instead? What's a good practice for handling CHAR
data types when I want to ignore trailing whitespace?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
如果你想
返回一条记录,请尝试
If you want
to return a record, try
我不认为有任何理由使用 CHAR 数据类型,即使它在 Oracle 中是 char(1) 。您可以更改数据类型吗?
I don't see any reason to use CHAR datatype even if it is char(1) in Oracle. Can you change the datatype instead?
加里的解决方案效果很好。这是一个替代方案。
如果您使用的是 Oracle JDBC 驱动程序,则对
prepareStatement()
的调用实际上会返回一个OraclePreparedStatement
,它具有一个setFixedCHAR()
方法自动用空格填充您的输入。显然,只有使用 Oracle 驱动程序时,转换才是安全的。
我建议您使用这个而不是 Gary 的答案的唯一原因是您可以更改列大小而无需修改 JDBC 代码。驱动程序会填充正确数量的空格,而开发人员无需了解/管理列大小。
Gary's solution works well. Here's an alternative.
If you are using an Oracle JDBC driver, the call to
prepareStatement()
will actually return anOraclePreparedStatement
, which has asetFixedCHAR()
method that automatically pads your inputs with whitespace.Obviously, the cast is only safe if you are using the Oracle driver.
The only reason I would suggest that you use this over Gary's answer is that you can change your column sizes without having to modify your JDBC code. The driver pads the correct number of spaces without the developer needing to know/manage the column size.
我对此有很好的解决办法。从数据库获取连接时,您必须添加一项属性。
或者在 Java 连接中,您可以使用以下代码:
I have nice fix for this. You have to add one property while getting connection from database.
or in Java connection you can use below code:
另一种方法是将你的sql修改为
the other way is modify your sql as
只需将 RTRIM() 添加到更新查询中的列名(已定义)即可。
Simply add RTRIM() to the column name(which is defimed) in the update query.