确保 Oracle 数据库表列中的字符串不超过 2000 字节

3

需要将错误字符串截断,以确保它适合于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);
}
4个回答

2
我建议您不要在Java中完成此操作,而是在执行INSERT时使用SQL语句进行操作。
例如,在Oracle中,您可以使用SUBSTR函数进行修剪,使用connection.prepareStatement
insert into mytable (col1, col2) values (?, substr(?, 0, 2000));

然后,在PreparedStatement上设置您的col1col2值,Oracle应该获取值的前2000个字符/字节/Oracle所做的任何内容,并将其设置。甚至可以使用存储过程来完成此操作,将整个字符串作为VARCHAR2参数传递给过程,然后修剪它并插入行。无需让应用程序涉及底层存储语义。

3
如果限制计数是字节,请使用SUBSTRB - user85421
“substrb” 这个东西似乎不起作用了... 以下语句不应该丢失一些字节吗? SELECT substrb('Příliš', 0, 6) FROM dual; 因为它并没有。 - Jaroslav Záruba

1

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


CLOB并不是VARCHAR2的替代品,这两种类型具有截然不同的特性,并且在Oracle和JDBC中处理方式也不同。 - skaffman
非常正确,但是看起来OP想要做一些(存储大块文本,没有提到索引)比VARCHAR更适合使用CLOB的事情。+1 - kdgregory

0

我认为你的方法应该可行,但是有意地丢失所有非ASCII字符是相当恶劣的。如果你有中文消息,它们将被完全替换成???

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


0

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接