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

Java 确保Oracle数据库表列中的字符串不超过2000字节,java,oracle,character-encoding,Java,Oracle,Character Encoding,要截断错误字符串,以便它确实适合Oracle表列VARCHAR2(2000字节) 设计力: 主要目标是适应表列 90-95%的字符串文本是异常消息和堆栈跟踪。但它可能包含一些带有法语、土耳其语字符的客户名称,我愿意忽略这些字符并将其视为?或者别的什么 我希望代码非常简单。数据库编码可以更改。可以引入汉字,但我希望代码能够正常工作 应该是“非常简单”,但它让我思考了一会儿 有什么建议 最好的选择可能是转换为ascii。但我提出了一种变体,虽然不好,但可能有效 public static Strin

要截断错误字符串,以便它确实适合Oracle表列VARCHAR2(2000字节)

设计力:

  • 主要目标是适应表列

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

  • 我希望代码非常简单。数据库编码可以更改。可以引入汉字,但我希望代码能够正常工作

  • 应该是“非常简单”,但它让我思考了一会儿

    有什么建议

    最好的选择可能是转换为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);
    }
    

    我认为您的方法应该有效,但故意丢失所有非ASCII字符是非常糟糕的。如果你曾经有过中文信息,它们将被替换为


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

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

    如果使用插入,则不需要截断字符串。

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

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

    insert into mytable (col1, col2) values (?, substr(?, 0, 2000));
    
    然后在
    PreparedStatement
    上设置
    col1
    col2
    的值,Oracle应获得该值的前2000个字符/字节/Oracle执行的任何操作,并进行设置


    对于存储过程来说,将整个字符串作为VARCHAR2参数传递给该过程,然后该过程对其进行修剪并插入行,这样做甚至是值得的。应用程序无需涉及底层存储语义。

    CLOB并不能替代VARCHAR2,这两种类型有着完全不同的特性,Oracle和JDBC对这两种类型的处理方式也不同。这是非常正确的,但听起来OP想要做些什么(存储大量文本,没有提到可索引性)比VARCHAR更适合CLOB。+1如果限制计数是字节,则使用
    SUBSTRB
    SUBSTRB
    似乎不起作用……是否应该丢失一些字节?
    选择SUBSTRB('Příliš',0,6)来自dual;
    ,因为它没有。