插入时间戳时的 H2 org.h2.jdbc.JdbcSQLSyntaxErrorException

Posted

技术标签:

【中文标题】插入时间戳时的 H2 org.h2.jdbc.JdbcSQLSyntaxErrorException【英文标题】:H2 org.h2.jdbc.JdbcSQLSyntaxErrorException when inserting a Timestamp 【发布时间】:2019-04-12 13:44:11 【问题描述】:

比较时间戳的 SQL 查询在 mysql 中有效,但在使用 H2 数据库时失败。

例如,这是产生异常的查询:

SELECT * FROM table WHERE time >= '2019-02-01T10:59:12.632Z' AND time <= '2019-04-12T10:59:12.632Z'

查询是使用 Java 代码动态创建的,上面的时间戳是 java.time.Instant 类型的。

我什至尝试过使用其他类型的日期/时间对象,结果相同。

此查询使用 MySQL 执行良好,但使用 H2 DB 时会引发以下错误:

 org.h2.jdbc.JdbcSQLSyntaxErrorException: Syntax error in SQL statement 
 "SELECT * FROM table WHERE  time>= 2019-04-10T13[*]:31:19.498Z AND  time <= 2019-04-07T13:31:19.498Z";
 SQL statement: 
 SELECT * FROM table WHERE  time >= 2019-04-10T13:31:19.498Z AND  time<= 2019-04-07T13:31:19.498Z

我发现使用冒号分隔的时间戳会导致这个问题令人费解,尤其是因为H2 docs use similar timestamps

【问题讨论】:

与其动态构建查询字符串,不如使用准备好的语句并将瞬间作为查询参数传递。 @OleV.V.这是正确的解决方案。我正在使用 Spring Boot,所以我只是将两个 Instants 作为参数传递给 jdbcTemplate.query() 方法。谢谢。 @OleV.V.我已经这样做了:) 【参考方案1】:

尝试正确转换日期字符串

SELECT * FROM table WHERE time >= str_to_date('2019-02-01 10:59:12.632 ', '%Y-%m-%d %T.%f') 
      AND time <=  str_to_date( '2019-04-12 10:59:12.632 ' , '%Y-%m-%d %T.%f') 

【讨论】:

【参考方案2】:

我正在使用 Spring Boot 的 JdbcTemplate 并按如下方式创建我的查询:

jdbcTemplate.query("SELECT * FROM table WHERE  time >= " + startTime + " AND " +  " time <= " + endTime, (rs, i) -> Accessor.readFromResultSet(rs));

将日期字符串作为Instant 对象传入。

感谢@OleV.V 的评论,解决方案是将日期对象作为对象参数传递:

jdbcTemplate.query("SELECT * FROM table WHERE  time >= ? AND time <= ?", new Object[]startTime, endTime, (rs, i) -> Accessor.readFromResultSet(rs));

【讨论】:

以上是关于插入时间戳时的 H2 org.h2.jdbc.JdbcSQLSyntaxErrorException的主要内容,如果未能解决你的问题,请参考以下文章

当数据重复且我没有时间戳时避免重复插入的建议

java.sql.SQLException:ORA-00932:不一致的数据类型:预期 DATE 在插入 Null 时间戳时得到 BINARY

创建时的 H2 数据库主键

创建数据库时的 H2 文件嵌入模式运行脚本(未初始化连接)

H2 时间戳 - 始终插入(或获取)当前日期

Bigtable:在行键上使用时间戳时避免热点