You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用UTC偏移(+00:00)的OffsetDateTime时HSQLDB MERGE操作失败

HSQLDB MERGE语句处理UTC偏移OffsetDateTime时的异常问题

使用HSQLDB的MERGE语句时,传入偏移为+00:00的OffsetDateTime会导致逻辑执行失败,但其他时区偏移(如+01:00)的情况下可以正常运行。经排查推测,问题根源在于UTC偏移的OffsetDateTime的toString()方法返回带Z后缀的字符串,而非+00:00格式;且单独使用INSERT语句时不存在该问题。

相关代码

创建表SQL

private static final String CREATE_TABLE_SQL = 
        "create table sample (" + 
           "code varchar2(50), " + 
           "updated timestamp with time zone" + 
        ")";

MERGE语句及原执行方法

private static final String MERGE_SQL =
        "merge into sample t " +
        "using (select ? as code, ? as updated from dual) val " +
        "on (t.code = val.code) " +
        "when matched then update set t.updated = val.updated " +
        "when not matched then insert(code, updated) values (val.code, val.updated)";

private int merge(String code, OffsetDateTime updated) throws SQLException {
    try (PreparedStatement statement = connection.prepareStatement(MERGE_SQL)) {
        statement.setString(1, code);
        statement.setObject(2, updated, Types.TIMESTAMP_WITH_TIMEZONE);
        return statement.executeUpdate();
    }
}

异常堆栈信息

java.sql.SQLDataException: data exception: invalid datetime format
            at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
            at org.hsqldb.jdbc.JDBCUtil.sqlException(Unknown Source)
            at org.hsqldb.jdbc.JDBCPreparedStatement.fetchResult(Unknown Source)
            at org.hsqldb.jdbc.JDBCPreparedStatement.executeUpdate(Unknown Source)
            at com.sample.DeletemeHsqlBugTest.merge(DeletemeHsqlBugTest.java:79)
            at com.sample.DeletemeHsqlBugTest.testMerge(DeletemeHsqlBugTest.java:58)
            at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
            ...
Caused by: org.hsqldb.HsqlException: data exception: invalid datetime format
            at org.hsqldb.error.Error.error(Unknown Source)
            at org.hsqldb.error.Error.error(Unknown Source)
            at org.hsqldb.types.DateTimeType.convertToDatetimeSpecial(Unknown Source)
            at org.hsqldb.types.DateTimeType.convertToType(Unknown Source)
            at org.hsqldb.ExpressionOp.getValue(Unknown Source)
            at org.hsqldb.StatementDML.getInsertData(Unknown Source)
            at org.hsqldb.StatementDML.executeMergeStatement(Unknown Source)
            at org.hsqldb.StatementDML.getResult(Unknown Source)
            at org.hsqldb.StatementDMQL.execute(Unknown Source)
            at org.hsqldb.Session.executeCompiledStatement(Unknown Source)
            at org.hsqldb.Session.execute(Unknown Source)
            ... 73 more

临时解决方案(不够优雅)

通过自定义DateTimeFormatter将UTC偏移的时间格式化为+00:00后缀,再以字符串形式传入参数:

private static final DateTimeFormatter FORMATTER = new DateTimeFormatterBuilder()
        .appendPattern("yyyy-MM-dd HH:mm:ss.SSS")
        .appendOffset("+HH:MM", "+00:00")
        .toFormatter();

private int merge(String code, OffsetDateTime updated) throws SQLException {
    try (PreparedStatement statement = connection.prepareStatement(MERGE_SQL)) {
        statement.setString(1, code);
        statement.setString(2, FORMATTER.format(updated));
        return statement.executeUpdate();
    }
}

内容的提问来源于stack exchange,提问作者lance-java

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.19 11:52:20