Oracle JDBC charset和4000 char限制

Aro*_*ion 8 java database oracle jdbc ojdbc

我们试图将UTF-16编码的字符串存储到AL32UTF8 Oracle数据库中.

我们的程序完全适用于使用WE8MSWIN1252charset 的数据库.当我们尝试在使用AL32UTF8它的数据库上运行它时会到达java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column.

在下面的测试用例中,只要我们的输入数据不会太长,一切正常.

输入字符串可以超过4000个字符.我们希望保留尽可能多的信息,即使我们意识到必须切断输入.

我们的数据库表使用CHAR关键字定义(见下文).我们希望这可以让我们存储多达4000个字符集.可以这样做吗?如果是这样,怎么样?

我们尝试将String转换为UTF8使用ByteBuffer但没有成功.OraclePreparedStatement.setFormOfUse(...)也没帮我们出去.

切换到a CLOB不是一种选择.如果字符串太长则需要剪切.

这是我们目前的代码:

public static void main(String[] args) throws Exception {
    String ip ="193.53.40.229";
    int port = 1521;
    String sid = "ora11";
    String username = "obasi";
    String password = "********";

    String driver = "oracle.jdbc.driver.OracleDriver";
    String url = "jdbc:oracle:thin:@" + ip + ":" + port + ":" + sid;
    Class.forName(driver);

    String shortData = "";
    String longData = "";
    String data;

    for (int i = 0; i < 5; i++)
        shortData += "é";

    for (int i = 0; i < 4000; i++)
        longData += "é";

    Connection conn = DriverManager.getConnection(url, username, password);

    PreparedStatement stat = null;
    try  {
        stat = conn.prepareStatement("insert into test_table_short values (?)");
        data = shortData.substring(0, Math.min(5, shortData.length()));
        stat.setString(1, data);
        stat.execute();

        stat = conn.prepareStatement("insert into test_table_long values (?)");
        data = longData.substring(0, Math.min(4000, longData.length()));
        stat.setString(1, data);
        stat.execute();
    } finally {
        try {
            stat.close();
        } catch (Exception ex){}
    }
}
Run Code Online (Sandbox Code Playgroud)

这是简单表的创建脚本:

CREATE TABLE test_table_short (
    DATA    VARCHAR2(5 CHAR);
);

CREATE TABLE test_table_long (
    DATA    VARCHAR2(4000 CHAR);
);
Run Code Online (Sandbox Code Playgroud)

测试用例在短数据上完美运行.然而,在长数据上它不断得到错误.即使我们longData只有3000个字符长,它仍然无法成功执行.

提前致谢!

Jus*_*ave 9

在Oracle 12.1之前,VARCHAR2列仅限于在数据库字符集中存储4000字节的数据,即使它已声明VARCHAR2(4000 CHAR).由于字符串中的每个字符都需要UTF-8字符集中的2个字节的存储空间,因此您无法在列中存储超过2000个字符.当然,如果你的某些角色实际上只需要1个字节的存储空间,或者其中一些字符需要超过2个字节的存储空间,那么这个数字就会改变.当数据库字符集是Windows-1252时,字符串中的每个字符只需要一个字节的存储空间,因此您可以在列中存储4000个字符.

由于你有更长的字符串,是否可以将列声明为CLOB而不是VARCHAR2?这将(有效地)消除长度限制(对于大小的限制CLOB取决于Oracle版本和块大小,但它至少在多GB范围内).

如果您恰好使用的是Oracle 12.1或更高版本,则该max_string_size参数允许您将的最大大小VARCHAR2从4000字节增加到32767字节.