甲骨文JDBC字符集和4000字符限制(Oracle JDBC charset and 4000 c

2019-07-30 11:57发布

我们正试图存储一个UTF-16编码字符串转换成AL32UTF8 Oracle数据库。

我们的计划完美的作品,使用的数据库上WE8MSWIN1252的字符集。 当我们试图使用一个数据库上运行它AL32UTF8它得到一个java.sql.SQLException: ORA-01461: can bind a LONG value only for insert into a LONG column

在下面的一切测试用例只要我们输入数据并没有得到太长时间正常工作。

输入字符串可以超过4000个字符。 我们希望保留尽可能多的信息越好,尽管我们实现了输入将被切断。

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

我们已经尝试了字符串转换为UTF8使用一个ByteBuffer没有成功。 OraclePreparedStatement.setFormOfUse(...)也没有帮助我们。

切换到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){}
    }
}

这是简单的表的创建脚本:

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

CREATE TABLE test_table_long (
    DATA    VARCHAR2(4000 CHAR);
);

测试用例完美的作品在短数据。 在长期的数据但是它一直得到错误。 即使我们longData只有3000个字符长,它仍然无法成功执行。

提前致谢!

Answer 1:

在此之前的Oracle 12.1,一个VARCHAR2列被限制为存储,如果它被声明甚至数据库字符集4000个字节数据的VARCHAR2(4000 CHAR) 由于在字符串中的每个字符需要2个字节存储在UTF-8字符集,你将不能超过2000个字符存储在列。 当然,如果你的一些人物其实需要的只是1存储字节,或者如果他们中的一些需要超过2个字节存储空间的数量会发生变化。 当数据库字符集为Windows-1252,在字符串中每个字符只需要一个单一的存储字节,所以你就可以存储在列4000个字符。

既然你有更长的字符串,将有可能宣布列作为CLOB而不是作为一个VARCHAR2 ? 这将(有效)去除长度的限制(有一个大小的限制CLOB依赖于Oracle版本和块大小,但它在多个GB范围内至少)。

如果你碰巧使用Oracle 12.1或更高版本,该max_string_size参数可以让你增加的最大尺寸VARCHAR2从4000个字节列32767个字节 。



Answer 2:

通过切割字符串到需要字节长度解决了这个问题。 请注意,这不能简单地使用来完成

stat.substring(0, length)

因为这会产生一个UTF-8字符串,可能是高达三倍长于允许的。

while (stat.getBytes("UTF8").length > length) {
  stat = stat.substring(0, stat.length()-1);
}

注意不要使用stat.getBytes(),因为这是依赖于一套“的file.encoding”,产生的是Windows 1252或UTF-8字节!

如果你使用Hibernate,您可以使用org.hibernate.Interceptor做到这一点!



文章来源: Oracle JDBC charset and 4000 char limit