【问题标题】:Charset issues in ojdbc7/ojdbc8 vs. correct behaviour in ojdbc6ojdbc7/ojdbc8 中的字符集问题与 ojdbc6 中的正确行为
【发布时间】: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.jarorai18n.jar: X�ARB -- 不正确
  • ojdbc7.jarorai18n.jar: X�ARB -- 不正确
  • ojdbc-6.jar:X²ARB -- 正确

通过使用UNISTR 并将语句更改为SELECT UNISTR(data) FROM datatable d WHERE d.id=2562456,我可以使ojdbc7.jarojdbc8.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


【解决方案1】:

这绝对看起来像是 JDBC 瘦驱动程序中的一个错误(我假设您正在使用瘦)。它可能与 LOB 预取有关,其中 CLOB 的长度、字符集 ID 和 LOB 数据的第一部分在带内发送。此功能是在 11.2 中引入的。作为一种解决方法,您可以通过设置连接属性来禁用 lob 预取

oracle.jdbc.defaultLobPrefetchSize

到“-1”。同时我会跟进这个错误以确保它得到修复。

【讨论】:

    【解决方案2】:

    请看Database JDBC Developer's Guide - Globalization Support

    基本的 Java 归档 (JAR) 文件 ojdbc7.jar,包含所有 提供完整全球化支持的必要类:

    • 字符集US7ASCIIWE8DECWE8ISO8859P1WE8MSWIN1252UTF8 的对象和集合的CHARVARCHAR 数据成员。

    CHARVARCHAR 的数据成员中使用任何其他字符集 对象或集合,您必须在 CLASSPATH 中包含 orai18n.jar 环境变量:

    ORACLE_HOME/jlib/orai18n.jar

    【讨论】:

    • 在发布此问题之前,我们已将本节阅读了 10 遍。正如我在问题中指出的那样,orai18n.jar is 在类路径中。
    • 我认为Oracle的声明很清楚:ojdbc7.jar(很可能还有ojdbc8.jar)不支持WE8ISO8859P15,即它们只支持US7ASCII,WE8DEC, WE8ISO8859P1、WE8MSWIN1252 和 UTF8。另一种解决方案是更改数据库的字符集,请参阅Character Set Migration
    • 出于这个特殊原因,我们确实在类路径中包含orai18n.jar。所以真的完全不清楚你的建议是什么(除了改变数据库字符集,这不一定是一个好选择)。
    猜你喜欢
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 2018-07-28
    • 2021-01-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-07-13
    相关资源
    最近更新 更多