java - Oracle JDBC 字符集和 4000 个字符限制

标签 java database oracle jdbc ojdbc

我们正在尝试将 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 个字符的任何字符集。 这可以做到吗?如果是,怎么做?

我们尝试使用 ByteBuffer 将字符串转换为 UTF8 但没有成功。 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 个字符长,它仍然无法成功执行。

提前致谢!

最佳答案

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

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

如果您碰巧使用的是 Oracle 12.1 或更高版本,max_string_size 参数允许您 increase the maximum size of a VARCHAR2 column from 4000 bytes to 32767 bytes .

关于java - Oracle JDBC 字符集和 4000 个字符限制,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11562819/

相关文章:

r - 在 r 中使用 for/nested 循环创建新列

java - 使用 JDBC 连接位于同一服务器上不同数据库中的 2 个 Oracle 表中的数据

java - 使用 Google Play 服务获取广播接收器中的位置

java - 转换整个 dom4j 元素的命名空间

java - 探索 Java 中的线程

Oracle 透明数据加密未解密访问

python - 从 Oracle 调用 Python

java - Minor GC 是什么时候触发的?

sql - 主聚集键默认顺序是升序的吗?

sql - "select max in group"的最佳性能查询?