Oracle:将日期与sysdate进行比较时的ora-01850

时间:2017-08-03 09:39:45

标签: sql oracle

将日期与sysdate进行比较时出现以下错误:ORA-01850:小时数必须介于0到23之间。

这是我的问题:

with cr as
 (select '1-2' heures from dual)
select mydate, to_date(mydate, 'yyyymmddhh24mi')
  from (select to_char(extract(year from sysdate), 'fm0009') ||
               to_char(extract(month from sysdate), 'fm09') ||
               to_char(extract(day from sysdate), 'fm09') ||
               to_char(h2.heure, 'fm09') || '45' mydate
          from (select to_number(h.intervalle_debut + i.l) heure
                  from (select to_number(regexp_substr(cr.heures,
                                                       '[^-]+',
                                                       1,
                                                       1))         intervalle_debut,
                               to_number(regexp_substr(cr.heures,
                                                       '[^-]+',
                                                       1,
                                                       2)) intervalle_fin
                          from cr) h,
                       (select level - 1 l from dual connect by level <=     24) i
                 where h.intervalle_fin - h.intervalle_debut >= i.l) h2)
where to_date(mydate, 'yyyymmddhh24mi') > sysdate;

小解释:

子查询“h2”返回以下两行:

heure
------
1
2

它对应于“cr”子查询中给出的范围1-2。 h2使用返回的小时数创建与今天相对应的日期。它还返回以下两行:

mydate
-------
201708030145
201708030245

日期看起来很好。小时数是1和2(这是正确的!)。

执行不带where子句的完整查询会返回这两个日期:

TO_DATE(MYDATE,'YYYYMMDDHH24MI
------------------------------
03/08/2017 01:45:00
03/08/2017 02:45:00

这仍然是正确的。 但是,当添加where子句“to_date(mydate,'yyyymmddhh24mi')&gt; sysdate”时,我得到ORA-01850。

怎么了?

2 个答案:

答案 0 :(得分:0)

是的,真的很奇怪。这个是有效的:

SELECT mydate, TO_DATE(mydate, 'yyyymmddhh24mi')
FROM ...;

但这不是:

SELECT mydate, TO_DATE(mydate, 'yyyymmddhh24mi')
FROM ...
WHERE TO_DATE(mydate, 'yyyymmddhh24mi') > SYSDATE;

ORA-01850: hour must be between 0 and 23

我做了一些重新格式化并简化了它。这个是工作(但我不知道为什么,即我不知道为什么你的查询不起作用)

WITH cr AS
    (SELECT '1-2' heures FROM dual),
i AS 
    (SELECT LEVEL - 1 l FROM dual connect BY LEVEL <= 24),
h AS
    (SELECT 
        TO_NUMBER(REGEXP_SUBSTR(cr.heures, '[^-]+', 1, 1)) intervalle_debut,
        TO_NUMBER(REGEXP_SUBSTR(cr.heures, '[^-]+', 1, 2)) intervalle_fin
    FROM cr),
h2 AS 
    (SELECT 
        TO_NUMBER(h.intervalle_debut + i.l) heure
    FROM h JOIN i ON h.intervalle_fin - h.intervalle_debut >= i.l),
t AS 
    (SELECT TO_CHAR(TRUNC(SYSDATE) + h2.heure/24 + 45/24/60, 'yyyymmddhh24mi') mydate
    FROM h2)
SELECT mydate, TO_DATE(mydate, 'yyyymmddhh24mi')
FROM t
WHERE TO_DATE(mydate, 'yyyymmddhh24mi') > SYSDATE;

您的查询的实际意图是什么?对我来说看起来有点过分了。这个做同样的事情:

WITH cr AS
    (SELECT '1-2' heures FROM dual),
h AS 
    (SELECT 
        REGEXP_SUBSTR(cr.heures, '[^-]+', 1, 1) intervalle_debut,
        REGEXP_SUBSTR(cr.heures, '[^-]+', 1, 2) intervalle_fin
    FROM cr),
t as    
    (SELECT TRUNC(SYSDATE) + (LEVEL-1+intervalle_debut)/24 + 45/24/60 AS mydate
    FROM h
    CONNECT BY LEVEL-1+intervalle_debut BETWEEN intervalle_debut AND intervalle_fin)
SELECT mydate
FROM t
WHERE mydate > SYSDATE;

答案 1 :(得分:0)

TO_DATE(mydate, 'yyyymmddhh24mi')>TO_DATE(sysdate, 'yyyymmddhh24mi')