【问题标题】:Oracle : ora-01850 when comparing a date to sysdateOracle:将日期与 sysdate 进行比较时出现 ora-01850
【发布时间】:2017-08-03 09:39:44
【问题描述】:

比较日期与 sysdate 时出现以下错误:ORA-01850 : Hours must be between 0 and 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') > sysdate”时,我得到 ORA-01850。

怎么了?

【问题讨论】:

  • 为什么要将日期存储在varchar 列中?
  • sysdate转换为字符值的复杂方法可以简化为to_char(sysdate, 'yyyymmddhh42')||'45'
  • 代替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,你可以更简单的TO_CHAR(TRUNC(sysdate) + h2.heure/24 + 45/24/60, 'yyyymmddhh24mi')
  • 查询不是真实的。我写了一个无需创建任何表即可重现问题的方法。当然可以简化,但这不是我的问题。问题是:“为什么 Oracle 在比较两个日期时会抛出错误?”。

标签: sql oracle


【解决方案1】:

是的,真的很奇怪。这个正在工作:

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;

您查询的实际意图是什么? Ìt对我来说看起来有点过分杀戮。这个也是一样的:

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;

【讨论】:

  • 感谢您的回复。我设法重写查询以避免对我来说真的很奇怪的错误。它可能与错误有关吗?
  • 可能与EXTRACT 函数有关:EXTRACT 将 expr 解释为 ANSI 日期时间数据类型。例如,EXTRACT 不将 DATE 视为旧版 Oracle DATE,而是将其视为 ANSI DATE,没有时间元素。因此,您只能从 DATE 值中提取 YEAR、MONTH 和 DAY。 - 只是一个想法。
【解决方案2】:

TO_DATE(mydate, 'yyyymmddhh24mi')&gt;TO_DATE(sysdate, 'yyyymmddhh24mi')

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-02-27
  • 1970-01-01
  • 2017-12-31
  • 2018-08-25
  • 1970-01-01
  • 2014-05-03
  • 1970-01-01
相关资源
最近更新 更多