如何在Oracle中使用WHERE子句查询TIMESTAMP WITH TIME ZONE列对应行
错误点分析
- 时间格式化模式使用错误:你定义的
DateTimeFormatter模式中用了n(代表纳秒,是独立的整数值)来匹配秒后的小数位,正确的秒小数位匹配符是S,这个错误会导致你解析出来的ZonedDateTime时间值和实际要查询的时间不一致,自然匹配不到数据库中的记录。 - 参数绑定方式冗余且易出错:你注释的代码中尝试用Oracle专属的
TIMESTAMPTZ类型封装参数,手动处理时区转换的过程容易出现精度、时区匹配错误,目前ojdbc8及以上版本的Oracle JDBC驱动原生支持java.time包下的时间类型直接绑定,不需要做额外的类型转换。 - 旧日期API的使用风险:你注释的
SimpleDateFormat、Calendar属于旧版日期API,本身存在线程安全问题,且时区、精度处理逻辑繁琐,很容易出现转换误差。
修正代码
// 要查询的时间字符串 String d = "2021-10-18 16:11:10.0 Europe/Paris"; // 修正格式化模式,用S匹配秒的小数位 DateTimeFormatter dtf2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S VV"); ZonedDateTime tm = ZonedDateTime.parse(d, dtf2); String query = "SELECT * FROM \"TEST_TIMESTAMP_WTZ_t2\" where time_with_zone = ?"; PreparedStatement ps = con.prepareStatement(query); // 直接绑定ZonedDateTime即可,JDBC驱动会自动适配Oracle的TIMESTAMP WITH TIME ZONE类型 ps.setObject(1, tm); ResultSet rs = ps.executeQuery(); while (rs.next()) { // 直接获取ZonedDateTime类型的结果 System.out.println(rs.getObject(2, ZonedDateTime.class)); }
如果使用的是低于ojdbc8的旧版本驱动,无法直接绑定
ZonedDateTime,可以用以下方式构造TIMESTAMPTZ参数:// 先把ZonedDateTime转成毫秒级时间戳 long timeMillis = tm.toInstant().toEpochMilli(); // 构造Oracle TIMESTAMPTZ对象,传入时区ID TIMESTAMPTZ dtm = new TIMESTAMPTZ(con, new java.sql.Timestamp(timeMillis), tm.getZone().getId()); ps.setObject(1, dtm);
内容的提问来源于stack exchange,提问作者Pravin Mangalam
相关产品推荐
相关产品推荐

