to_date ora-01847 月份中的某天必须介于 1 和该月的最后一天之间

Posted

技术标签:

【中文标题】to_date ora-01847 月份中的某天必须介于 1 和该月的最后一天之间【英文标题】:to_date ora-01847 day of month must be between 1 and last day of month 【发布时间】:2013-03-07 16:59:32 【问题描述】:

我正在尝试执行以下查询,但收到此错误:

to_date ora-01847 day of month must be between 1 and last day of month

查询是检查两个不同表中日期和时间的重叠

table1 (emp_num1 number,start_date1 date,start_time1 varchar2,end_date1 date,end_time2 varchar2)

table2(emp_num2 number,start_date2 date,start_time2 varchar2,end_date2 date,end_time2 varchar2)

select *
  from table1 t1
      ,table2 t2
 where t1.emp_num 1 = t2.emp_num2
   and to_timestamp(to_char(start_date1,'DD-MON-YYYY')||' '||NVL(start_time1,'00:00'),'DD-MON-YYYY HH24:MI')
       between
      to_timestamp(to_char(start_date2,'DD-MON-YYYY')||' '||NVL(start_time2,'00:00'),'DD-MON-YYYY HH24:MI')
       and
      to_timestamp(to_char(end_date2,'DD-MON-YYYY')||' '||NVL(end_time2,'00:00'),'DD-MON-YYYY HH24:MI')
      or
      to_timestamp(to_char(end_date1,'DD-MON-YYYY')||' '||NVL(end_time1,'00:00'),'DD-MON-YYYY HH24:MI')
       between
      to_timestamp(to_char(start_date2,'DD-MON-YYYY')||' '||NVL(start_time2,'00:00'),'DD-MON-YYYY HH24:MI')
       and
      to_timestamp(to_char(end_date2,'DD-MON-YYYY')||' '||NVL(end_time2,'00:00'),'DD-MON-YYYY HH24:MI')

上述查询导致错误:

to_date ora-01847 day of month must be between 1 and last day of month

我尝试运行查询

select to_timestamp(to_char(start_date1,'DD-MON-YYYY')||' '||NVL(start_time1,'00:00'),'DD-MON-YYYY HH24:MI') from table1

没有遇到错误。

【问题讨论】:

四个日期字段之一是否有可能具有NULL 值? 尝试用 NULL 代替 start_date1 的测试查询:我敢打赌它会给出同样的错误。 日期字段是必填字段...所以所有表格都没有空日期字段 然后尝试针对所有涉及的字段和表运行测试查询的变体。分享和享受。 【参考方案1】:

重现错误:

SELECT NVL(SYSDATE,'00:00')
FROM DUAL

ORA-01847: 日期必须介于 1 和最后一天之间

NVL() description 说:

参数 expr1 和 expr2 可以具有任何数据类型。如果他们的数据 类型不同,则 Oracle 数据库隐式转换为 另一个。如果它们不能被隐式转换,那么数据库 返回错误。隐式转换实现如下:

如果 expr1 是字符数据,那么 Oracle 数据库在比较它们之前将 expr2 转换为 expr1 的数据类型,并在 expr1 的字符集。

如果 expr1 是数字,则 Oracle 数据库确定哪个参数具有最高的数字优先级,隐式转换另一个 该数据类型的参数,并返回该数据类型。

所以我们可以简化重现情况:

SELECT TO_DATE('00:00')
FROM DUAL

由于您没有提供格式,因此假设为 NLS_DATE_FORMAT,因此错误:'00' is not a valid day。

(我真的不知道您要做什么,但您可以尝试使用纯日期函数。)

【讨论】:

但是根据查询中的表定义,start_time 和 end_time 字段被声明为 VARCHAR2。因此,我认为不是这样。好主意,不过。 那么对不起。我不知道列类型,所以我只是猜测。【参考方案2】:

您的格式需要修正。这是您的初始设置:

SELECT '07-MAR-2013' start_date -- char
     , NULL          start_time -- char
 FROM dual
/

最终格式 - 不需要 NVL。但是如果你必须添加 NVL(start_time, '00:00'):

SELECT to_timestamp(start_date||' '||start_time, 'DD-MON-YYYY HH24:MI:SS') t_stamp
  FROM
  (
   SELECT '07-MAR-2013'      start_date -- char
        , NVL(NULL, '00:00') start_time -- char - NVL is optional 
    FROM dual
  )
 /

 3/7/2013 12:00:00.000000000 AM

如果您删除 start_time compl,您将获得相同的结果。通常要比较日期,您应该使用 TRUNC 删除时间部分。

SELECT to_timestamp('07-MAR-2013', 'DD-MON-YYYY HH24:MI:SS') start_date_only 
  FROM dual
/   

3/7/2013 12:00:00.000000000 AM

 SELECT trunc(to_timestamp('07-MAR-2013', 'DD-MON-YYYY HH24:MI:SS')) start_date_only FROM dual
 /

3/7/2013

【讨论】:

以上是关于to_date ora-01847 月份中的某天必须介于 1 和该月的最后一天之间的主要内容,如果未能解决你的问题,请参考以下文章

C# 日期时间格式化

DateTime 时间格式

yyyy-MM-dd HH:mm:ss

c++判断某年某月有多少天

oracle中to_date详细用法示例(oracle日期格式转换)

ORA-01839“日期对于指定的月份无效”对于 where 子句中的 to_date