【发布时间】:2018-08-28 16:21:57
【问题描述】:
我们有一个具有以下字符集设置的 Oracle 数据库
SELECT 参数,值 FROM nls_database_parameters WHERE 参数,如 'NLS%CHARACTERSET'
NLS_NCHAR_CHARACTERSET: AL16UTF16
NLS_CHARACTERSET: WE8ISO8859P15
在这个数据库中,我们有一个带有CLOB 字段的表,它有一条以以下字符串开头的记录,显然存储在 ISO-8859-15 中:X²ARB(这里正确转换为 unicode,特别是2-上标重要且正确)。
然后我们有以下一段简单的代码来获取值,它应该通过 Oracle 中的全球化支持自动将字符集转换为 unicode:
private static final String STATEMENT = "SELECT data FROM datatable d WHERE d.id=2562456";
public static void main(String[] args) throws Exception {
Class.forName("oracle.jdbc.driver.OracleDriver");
try (Connection conn = DriverManager.getConnection(DB_URL);
ResultSet rs = conn.createStatement().executeQuery(STATEMENT))
{
if (rs.next()) {
System.out.println(rs.getString(1).substring(0, 5));
}
}
}
运行代码打印:
-
ojdbc8.jar和orai18n.jar:X�ARB-- 不正确 -
ojdbc7.jar和orai18n.jar:X�ARB-- 不正确 - 与
ojdbc-6.jar:X²ARB-- 正确
通过使用UNISTR 并将语句更改为SELECT UNISTR(data) FROM datatable d WHERE d.id=2562456,我可以使ojdbc7.jar 和ojdbc8.jar 返回正确的值,但这需要对代码进行未知数量的更改,因为这可能不是仅出现问题的地方。
我可以对客户端或服务器配置做些什么以使 所有 查询返回正确编码的值而无需修改语句?
【问题讨论】:
-
问题:当列类型为 VARCHAR2(而不是 CLOB)时,是否也会出现此问题?此数据库是否已升级或更改其字符集?最后 orai18n.jar 与此无关。如果没有 orai18n.jar,这应该可以正常工作。
-
不,它似乎是特定于 CLOB 的。更重要的是,一位同事刚刚发现,从 12.1 驱动程序行中新下载的
jodbc6.jr的行为似乎与 7 和 8 的行为一致。显然我们只能使用jodbc-6.jar得到正确的行为多年来,我们在早期版本的产品中一直如此。所以一定有一个变化以类似于 7 和 8 的方式影响 6 :( -
这绝对看起来像是 JDBC 瘦驱动程序中的一个错误(我假设您正在使用瘦)。它可能与 LOB 预取有关,其中 CLOB 的长度、字符集 ID 和 LOB 数据的第一部分在带内发送。此功能是在 11.2 中引入的。您可以尝试通过将连接属性“oracle.jdbc.defaultLobPrefetchSize”设置为“-1”来禁用 lob 预取吗?
-
@JeandeLavarene 它奏效了。请把它作为答案发布,我很乐意接受!
标签: java oracle oracle11g character-encoding ojdbc