'select' 准备好的带有时间戳的语句 returns 总是空的 RecordSet
'select' preparedStatement wih Timestamp returns always empty RecordSet
我尝试使用 JDBC 瘦驱动程序从 ORACLE 数据库 table 检索记录。
我正在使用的准备好的声明:
(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
returns 预期的数据。
当我查询时来自相同 table 的另一列的字符串与准备好的语句结果是好的。
我在这里缺少什么?重点在哪里?有什么想法吗?
说清楚:重点不是在(2)中识别一种错误的date/time格式转换。这将始终导致 oracle 错误消息,并且可以轻松修复。
问题是:为什么preparedStatement(1) 返回的RecordSet 为空(= 不是一条记录)而没有任何错误通知?如果时间戳格式有任何错误,为什么没有错误或警告?
检查您的 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
A 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
}
}
我尝试使用 JDBC 瘦驱动程序从 ORACLE 数据库 table 检索记录。 我正在使用的准备好的声明: (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
returns 预期的数据。 当我查询时来自相同 table 的另一列的字符串与准备好的语句结果是好的。
我在这里缺少什么?重点在哪里?有什么想法吗?
说清楚:重点不是在(2)中识别一种错误的date/time格式转换。这将始终导致 oracle 错误消息,并且可以轻松修复。
问题是:为什么preparedStatement(1) 返回的RecordSet 为空(= 不是一条记录)而没有任何错误通知?如果时间戳格式有任何错误,为什么没有错误或警告?
检查您的 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
A 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
}
}