【问题标题】:Making sure String does not exceeds 2000 bytes in Oracle database table column确保 Oracle 数据库表列中的字符串不超过 2000 字节
【发布时间】:2009-10-21 10:46:32
【问题描述】:

想要截断错误字符串,以确保它适合 Oracle 表列 VARCHAR2(2000 BYTE)

设计力量:

  1. 主要目标是适合表格列。

  2. 90-95% 的字符串文本是异常消息和堆栈跟踪。但它可能包含一些带有法语、土耳其语字符的客户名称,我愿意忽略这些字符并将其视为?或其他。

  3. 我希望代码非常简单。数据库编码可以改变。可以引入汉字,但我还是想让代码工作。

应该是“非常简单”,但它让我思考了一段时间。

什么是建议?

可能最好的选择是转换为 ascii。但我想出了一个不好但可能有效的变体。

public static String trimStringToBytes(StringBuilder builder, int maximumBytes)
{
    String truncatedString = builder.length() > maximumBytes ?  builder.substring(0, maximumBytes) : builder.toString();

    byte[] bytes;
    String asciiCharsetName = "US-ASCII";
    try
    {
        bytes = truncatedString.getBytes(asciiCharsetName);
    }
    catch (UnsupportedEncodingException e)
    {
        //not really possible as JVM should support always US-ASCII but anyway
        int worstCaseScenarioBytesPerCharacter = 4;
        bytes = truncatedString.substring(0, truncatedString.length() / worstCaseScenarioBytesPerCharacter).getBytes();
    }

    return new String(bytes, 0, bytes.length > maximumBytes ? maximumBytes : bytes.length);
}

【问题讨论】:

    标签: java oracle character-encoding


    【解决方案1】:

    我建议不要在 Java 中执行此操作,而是在执行 INSERT 时在 SQL 中执行此操作。

    例如,在 Oracle 中,您可以使用 SUBSTR 函数进行修剪,使用 connection.prepareStatement

    insert into mytable (col1, col2) values (?, substr(?, 0, 2000));
    

    然后在PreparedStatement 上设置col1col2 值,Oracle 应该获取该值的前2000 个字符/字节/whatever-it-is-that-oracle-does,并设置它。

    使用存储过程甚至可能值得这样做,将整个字符串作为 VARCHAR2 参数传递给过程,然后修剪它并插入行。应用程序无需涉及底层存储语义。

    【讨论】:

    • 如果限制计数为字节,请改用SUBSTRB
    • substrb 的东西似乎不起作用...跟随不应该丢失一些字节吗? SELECT substrb('Příliš', 0, 6) FROM dual;因为没有。
    【解决方案2】:

    如果您使用CLOB,则无需截断字符串。

    【讨论】:

    • CLOB 不是 VARCHAR2 的替代品,这两种类型具有完全不同的特征,Oracle 和 JDBC 的处理方式也不同。
    • 非常正确,但听起来 OP 想要做一些比 VARCHAR 更适合 CLOB 的事情(存储大量文本,没有提及可索引性)。 +1
    【解决方案3】:

    我认为您的方法应该可行,但是故意丢失所有非 ASCII 字符是非常讨厌的。如果您有中文消息,它们将被完全替换为???

    IMO 最好的办法是在插入查询中使用 SQL 函数进行修剪。这样可以确保您永远不会超过列大小并丢失尽可能少的数据。与尝试在 Java 代码中进行编码感知修剪相比,它也不太容易出错。

    【讨论】:

      【解决方案4】:

      是否可以将列更改为 VARCHAR2(2000 CHAR)?这将完全消除编码问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2017-09-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多