2017-08-03 204 views
1

我比較的日期SYSDATE時收到以下錯誤:ORA-01850:時間必須介於0和23甲骨文:比較日期時ORA-01850至SYSDATE

這裏是我的查詢:

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')> sysdate」時,我得到了ORA-01850。

怎麼了?

+0

你爲什麼要存儲在'varchar'列的日期? –

+0

將'sysdate'轉換爲字符值的複雜方法可以簡化爲'to_char(sysdate,'yyyymmddhh42')||'45'' –

+0

而不是'to_char(提取(從sysdate年),'fm0009')| | to_char(提取(sysdate中的月份),'fm09')|| to_char(提取(sysdate中的日期),'fm09')|| to_char(h2.heure,'fm09')|| '45'mydate'你可以簡化'TO_CHAR(TRUNC(sysdate)+ h2.heure/24 + 45/24/60,'yyyymmddhh24mi')' –

回答

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; 
+0

感謝您的回覆。我設法重寫查詢以避免對我來說很奇怪的錯誤。它可能與一個錯誤有關嗎? – Vincent

+0

也許它與[EXTRACT](http://docs.oracle.com/database/121/SQLRF/functions067.htm#SQLRF00639)函數有關:_EXTRACT將expr解釋爲ANSI datetime數據類型。例如,EXTRACT將DATE視爲傳統Oracle DATE,而不是作爲ANSI DATE,而不包含時間元素。因此,您只能從DATE值中提取YEAR,MONTH和DAY._ - 只是一個想法。 –

0

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

+0

雖然這段代碼片段可能是一個解決方案,但它會[如果它包含一個解釋](/ meta.stackexchange.com/q/114762)*如何*和*爲什麼*這會解決問題[大大改進]。請編輯您的答案以添加解釋,並指出適用的限制和假設。 – whrrgarbl

+0

sysdate已經是日期。無需添加「to_date」。 – Vincent