Oracle JDBC预编译语句抛出ORA-00905缺失关键字异常求助
问题原因分析
这个ORA-00905错误的核心原因是你在PreparedStatement的SQL语句里错误地将Oracle的timestamp关键字和占位符?绑定在一起了。
直接执行硬编码语句时,timestamp '2021-07-07 00:00:00'是Oracle合法的时间字面量语法——关键字timestamp和后面的字符串值是一个整体,数据库能正确解析。但用PreparedStatement时,占位符?的作用是替换单个参数值,而不是替换字面量的一部分。当驱动把timestamp ?发送给数据库时,数据库会认为timestamp后面应该跟具体的字符串值,而不是占位符,因此抛出“缺少关键字”的错误。
解决方法
你只需要两步就能修复这个问题:
1. 修改SQL语句,移除timestamp关键字
把原SQL中的created_at BETWEEN timestamp ? AND timestamp ?改成:
SELECT COUNT(*) as count FROM my_table WHERE product_id = ? AND status = ? AND created_at BETWEEN ? AND ? ;
2. 使用JDBC的setTimestamp()方法传入时间参数
在Java代码中,将你的时间值转换为java.sql.Timestamp类型,然后通过PreparedStatement.setTimestamp()方法设置参数,示例代码如下:
// 假设你已经获取了数据库连接connection String sql = "SELECT COUNT(*) as count FROM my_table WHERE product_id = ? AND status = ? AND created_at BETWEEN ? AND ?"; try (PreparedStatement pstmt = connection.prepareStatement(sql)) { // 设置字符串参数 pstmt.setString(1, "TEST"); pstmt.setString(2, "SUCCESS"); // 设置时间参数(示例:构造开始和结束时间) Timestamp startTime = Timestamp.valueOf("2021-07-07 00:00:00"); Timestamp endTime = Timestamp.valueOf("2021-07-07 23:59:59"); pstmt.setTimestamp(3, startTime); pstmt.setTimestamp(4, endTime); // 执行查询并处理结果 ResultSet rs = pstmt.executeQuery(); if (rs.next()) { int count = rs.getInt("count"); System.out.println("匹配的记录数:" + count); } } catch (SQLException e) { e.printStackTrace(); }
补充说明
JDBC驱动会自动将java.sql.Timestamp类型的参数转换为Oracle数据库能识别的时间格式,完全不需要在SQL中手动添加timestamp关键字。这种方式不仅解决了语法错误,还符合PreparedStatement参数化查询的最佳实践,能有效避免SQL注入风险。
内容的提问来源于stack exchange,提问作者Yaz
相关产品推荐
相关产品推荐

