4

我正在尝试将 SQL 字符串数组绑定到准备好的语句,并且对于某些数据库字符集,数组的值变为空。如果我绑定简单的字符串(不在数组中),它就可以工作。

如果字符集(v$nls_parameters 中的 NLS_CHARACTERSET)是 AL32UTF8,它可以正常工作。如果是 WE8ISO8859P15,那么我可以绑定字符串,但不能绑定字符串数组。不同之处似乎在于 Oracle JDBC 具有支持转换的特定字符集列表,而 ISO-8859-15 不是其中的一部分。

这解释了部分问题,因为当它在数据库中发现它时,它会将所有字符串转换为 null。但是当字符串不在数组中时转换确实有效......所以我很困惑。

我的整个测试如下。我使用的表类型定义为create type t_v4000_table as table of varchar2(4000);

Connection connection;

@Before
public void setup() throws SQLException {
    OracleDataSource ds = new OracleDataSource();
    ds.setUser("aaa");
    ds.setPassword("a");
    ds.setURL("jdbc:oracle:thin:@server:1521:orcl");
    connection = ds.getConnection();
}

@Test
// works with both AL32UTF8 and WE8ISO8859P15
public void testScalar() throws SQLException {
    CallableStatement stmt = connection.prepareCall("declare a varchar2(4000) := ?; "
            + "begin if a is null then raise_application_error(-20000,'null'); end if; end;");
    stmt.setString(1, "a");
    stmt.execute();
}

@Test
// works only with AL32UTF8
public void testArray() throws SQLException {
    ArrayDescriptor descriptor = ArrayDescriptor.createDescriptor("T_V4000_TABLE", connection);
    String[] array = new String[] {"a"};
    Array sqlArray = new ARRAY(descriptor, connection, array);
    CallableStatement stmt = connection.prepareCall("declare a t_v4000_table := ?; " +
            "begin if a(1) is null then raise_application_error(-20000,'null'); end if; end;");
    stmt.setArray(1, sqlArray);
    stmt.execute();
}

我怀疑我在声明和绑定数组的方式上做错了,但我不知道是什么。任何的想法?

4

1 回答 1

3

解决方案,以及对象/集合内的字符串与否之间的区别,有据可查,实际上:

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

  • 未作为 Oracle 对象或集合类型的数据成员检索或插入的 CHAR、VARCHAR、LONGVARCHAR 或 CLOB 数据的 Oracle 字符集。
  • 字符集 US7ASCII、WE8DEC、WE8ISO8859P1、WE8MSWIN1252 和 UTF8 的对象和集合的 CHAR 或 VARCHAR 数据成员。

要在对象或集合的 CHAR 或 VARCHAR 数据成员中使用任何其他字符集,您必须在应用程序的 CLASSPATH 环境变量中包含 orai18n.jar。

在 CLASSPATH 中添加 orai18n.jar 后,它就像一个魅力

于 2012-05-04T16:59:43.367 回答