ojdbc7/ojdbc8 中的字符集问题与 ojdbc6 中的正确行为

Charset issues in ojdbc7/ojdbc8 vs. correct behaviour in ojdbc6

我们有一个具有以下字符集设置的 Oracle 数据库

SELECT parameter, value FROM nls_database_parameters WHERE parameter like 'NLS%CHARACTERSET'

NLS_NCHAR_CHARACTERSET: AL16UTF16
NLS_CHARACTERSET: WE8ISO8859P15

在这个数据库中,我们有一个带有 CLOB 字段的 table,它有一条以以下字符串开头的记录,显然存储在 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));
        }
    }
}

运行 代码打印:

通过使用 UNISTR 并将语句更改为 SELECT UNISTR(data) FROM datatable d WHERE d.id=2562456 我可以将 ojdbc7.jarojdbc8.jar 变为 return 正确的值,但这需要对代码进行了未知数量的更改,因为这可能不是唯一出现问题的地方。

我可以对客户端或服务器配置做些什么来使 所有 查询 return 正确编码的值而无需修改语句吗?

请看Database JDBC Developer's Guide - Globalization Support

The basic Java Archive (JAR) file ojdbc7.jar, contains all the necessary classes to provide complete globalization support for:

  • CHAR or VARCHAR data members of object and collection for the character sets US7ASCII, WE8DEC, WE8ISO8859P1, WE8MSWIN1252, and UTF8.

To use any other character sets in CHAR or VARCHAR data members of objects or collections, you must include orai18n.jar in the CLASSPATH environment variable:

ORACLE_HOME/jlib/orai18n.jar

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

来禁用 lob 预取

oracle.jdbc.defaultLobPrefetchSize

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