面对日期功能的问题

时间:2018-03-19 13:23:52

标签: oracle date

我试图从dba_scheduler_job_run_details视图中获取值。 其中log_date> (SYSDATE - 5 /(24 * 60))(即最后5分钟的数据)

但它没有为我提供正确的价值。

如需样品,请查看以下数据: SQL查询:

SELECT SYSDATE, SYSDATE - 5/(24*60),LOG_DATE,TRUNC(LOG_DATE),TO_CHAR(LOG_DATE,'YYYY/MM/DD HH:MI:SS')
FROM dba_scheduler_job_run_details 
WHERE LOG_DATE  > (SYSDATE - 5/(24*60))
ORDER BY LOG_DATE DESC;

O / P: 附加图片enter image description here

1 个答案:

答案 0 :(得分:2)

这是因为log_datetimestamp with timezone数据类型,当你使用date数据类型加入它时,当Oracle进行隐式转换比较时,它会导致两个不同的时间:

SQL> SELECT SYSTIMESTAMP, CAST(SYSDATE AS TIMESTAMP WITH TIME ZONE) time_with_tz FROM dual;
SYSTIMESTAMP                                                                     TIME_WITH_TZ
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
19-MAR-18 09.57.07.654161 AM -04:00                                              19-MAR-18 09.57.07.000000 AM +05:30

因此,如果我在偏移量为-4:00的服务器上执行偏移量为+5:30的时区查询,Oracle会将SYSDATE - 5/(24*60)转换为sysdate - (9:30 + 0:05)

告诉Oracle明确地将log_date转换为日期,然后按照以下方式应用> (SYSDATE - 5/(24*60)的文件管理器,你会没事的:

SELECT SYSDATE, SYSDATE - 5/(24*60),LOG_DATE,TRUNC(LOG_DATE),TO_CHAR(LOG_DATE,'YYYY/MM/DD HH:MI:SS')
FROM dba_scheduler_job_run_details 
WHERE cast(LOG_DATE AS DATE)  > (SYSDATE - 5/(24*60))
ORDER BY LOG_DATE DESC;

更新:由于以下原因,此查询可能存在性能问题,

  

1)Oracle将转换LOG_DATE列的每一行的数据类型   到目前为止的时区的时间戳。

     

2)LOG_DATE列的构建索引(如果有)将不会使用到期   到CAST功能。

更好的解决方案是将sysdate - 5 /(24 * 60)转换为带时区的时间戳,您必须知道Oracle服务器的时区,假设服务器位于UTC -4:00,下面查询应该可以正常工作:

SELECT SYSDATE, SYSDATE - 5/(24*60),LOG_DATE,TRUNC(LOG_DATE),TO_CHAR(LOG_DATE,'YYYY/MM/DD HH:MI:SS')
FROM dba_scheduler_job_run_details 
WHERE LOG_DATE > TO_TIMESTAMP_TZ (to_char(SYSDATE - 5/(24*60), 'YYYY-MM-DD HH24:MI:SS')  || ' -4:00', 'YYYY-MM-DD HH24:MI:SS TZH:TZM')
ORDER BY LOG_DATE DESC;

@mathguy建议的另一种更简单的方法,使用INTERVAL函数:

SELECT SYSDATE, SYSDATE - 5/(24*60),LOG_DATE,TRUNC(LOG_DATE),TO_CHAR(LOG_DATE,'YYYY/MM/DD HH:MI:SS')
FROM dba_scheduler_job_run_details 
WHERE LOG_DATE > SYSTIMESTAMP - INTERVAL '5' MINUTE
ORDER BY LOG_DATE DESC;