【问题标题】:'select' preparedStatement wih Timestamp returns always empty RecordSet'select'preparedStatement with Timestamp 返回总是空的 RecordSet
【发布时间】:2015-12-17 03:02:46
【问题描述】:

我尝试使用 JDBC 瘦驱动程序从 ORACLE 数据库表中检索记录。 我正在使用的准备好的语句: (1)

SELECT (t1.LOGGED_TIME - ?) AS TDIFF, t1.ID, t1.STATUS, t1.LOGGED_TIME, t1.SERVER_TIME 
        FROM table_1 t1 
        WHERE (
          ((t1.LOGGED_TIME - ?) <= INTERVAL '10' DAY) 
          AND ((t1.LOGGED_TIME - ?) >= INTERVAL '-10' DAY)) 
        ORDER BY t1.LOGGED_TIME DESC

其中 t1.LOGGED_TIME 表示时间戳列。每三个参数都是用

设置的相同时间戳
java.sql.Timestamp controlTime = Timestamp.valueOf("2014-08-15 03:52:00");

lookupTime.setTimestamp(1, controlTime);
lookupTime.setTimestamp(2, controlTime);
lookupTime.setTimestamp(3, controlTime);

执行代码工作正常 - 不显示异常或警告。然而

返回的结果集
rs =  lookupTime.executeQuery();

是空的。

将查询设置为 (2)

SELECT (t1.LOGGED_TIME - TO_TIMESTAMP('2014-08-15 03:52', 'yyyy-mm-dd hh24:mi')) AS TDIFF, t1.ID, t1.STATUS, t1.LOGGED_TIME, t1.SERVER_TIME 
FROM table_1 t1 
WHERE (
  ((t1.LOGGED_TIME - TO_TIMESTAMP('2014-08-15 03:52', 'yyyy-mm-dd hh24:mi')) <= INTERVAL '10' DAY) 
  AND ((t1.LOGGED_TIME - TO_TIMESTAMP('2014-08-15 03:52', 'yyyy-mm-dd hh24:mi')) >= INTERVAL '-10' DAY)) 
ORDER BY t1.LOGGED_TIME DESC

返回预期的数据。 当我查询例如来自同一个表的另一列的字符串,带有准备好的语句,结果是好的。

我在这里缺少什么?重点在哪里?有什么想法吗?

说清楚:重点不是在(2)中识别出一种错误的日期/时间格式转换。这总是会导致一个 oracle 错误消息,并且可以很容易地修复。

问题是:为什么preparedStatement (1) 返回的RecordSet 保持为空(= 不是一条记录)而没有任何错误通知?如果时间戳格式有任何错误,为什么没有错误或警告?

【问题讨论】:

  • TO_TIMESTAMP('2014-08-15 03:52', 'dd.mm.yy hh24:mi'):这没有多大意义。模式与字符串不匹配。
  • 如何相信您第二个查询返回任何内容,而此查询由于错误而无法事件运行? ==> 模式与TO_TIMESTAMP('2014-08-15 03:52', 'dd.mm.yy hh24:mi') 中的值不匹配?
  • 你是对的。复制和粘贴错误。我已经更正了...
  • 您的查询查找 >= 10 天和 default 时区解析字符串,这可能与执行 TO_TIMESTAMP() 时使用的时区不同,后者使用数据库的时区(或设置连接时由驱动程序)。
  • @JB Nizet:不完全是。我正在搜索时差 10 天和时差 >= -10 天。因此,应该返回 20 天的时间范围,提前 10 天和某个事件后 10 天。至少这是我的意图:)

标签: java oracle jdbc prepared-statement recordset


【解决方案1】:

检查您的TO_TIMESTAMP 格式:

TO_TIMESTAMP('2014-08-15 03:52',
               'dd.mm.yy hh24:mi')

Aug. 14, 2015,不是Aug. 15, 2014

更新

实际上,我在尝试该错误时收到以下错误:

ORA-01843: not a valid month
01843. 00000 -  "not a valid month"

更新2

Java Timestamp 映射到 Oracle DATE 数据类型,而不是 TIMESTAMP。不知道这是否会有所不同,但您可以试试TO_TIMESTAMP(?)

不过,我会更改查询以允许在 LOGGED_TIME 上使用潜在索引:

SELECT ID, STATUS, LOGGED_TIME, SERVER_TIME
  FROM table_1
 WHERE LOGGED_TIME BETWEEN ? AND ?
 ORDER BY LOGGED_TIME DESC

然后用 Java 做所有的数学运算:

Timestamp controlTime = Timestamp.valueOf("2014-08-15 03:52:00");
Calendar cal = Calendar.getInstance();
cal.setTime(controlTime);
cal.add(Calendar.DAY_OF_MONTH, -10);
lookupTime.setTimestamp(1, new Timestamp(cal.getTimeInMillis()));
cal.setTime(controlTime);
cal.add(Calendar.DAY_OF_MONTH, 10);
lookupTime.setTimestamp(2, new Timestamp(cal.getTimeInMillis()));
try (ResultSet rs = lookupTime.executeQuery()) {
    while (rs.next()) {
        long tdiffInSeconds = (rs.getTimestamp("LOGGED_TIME").getTime() - controlTime.getTime()) / 1000;
        // other code
    }
}

【讨论】:

  • resultSet 为空的原因是:程序使用的架构与 SQL Developer 使用的架构不同。因为我不是数据库的所有者,所以我必须使用数据库管理员提供的名称。所以问题就解决了。不过感谢您的回答。我已经按照建议执行(也是索引提示)
  • 在 Java 中进行日期运算无需过度复杂化;将相同的变量传递给查询两次并使用WHERE LOGGED_TIME BETWEEN ? AND ? + 10WHERE LOGGED_TIME BETWEEN ? AND ? + INTERVAL '10' DAY 就足够了。
猜你喜欢
  • 2018-11-02
  • 2021-01-28
  • 1970-01-01
  • 2019-12-31
  • 2012-10-12
  • 2016-07-11
  • 2017-12-19
  • 2019-12-02
  • 1970-01-01
相关资源
最近更新 更多