You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

数字转日期报错‘day of month must be between 1 and last day of month’排查

问题

编写SQL代码识别错误数据时遇到报错。数据中的日期列是数字类型,需要转换为日期格式(例如10322→01.03.2022),代码如下:

select *
  from (select *****_date,
               *****_hold_no,
               case
                 when length(*****_end_date) = 5 then
                  to_date(lpad(*****_end_date, 6, '0'), 'ddmmyy')
                 else
                  to_date(*****_end_date, 'ddmmyy')
               end as *****_end_date,
               case
                 when length(*****_start_date) = 5 then
                  to_date(lpad(*****_start_date, 6, '0'), 'ddmmyy')
                 else
                  to_date(*****_start_date, 'ddmmyy')
               end as *****_start_date
          from ods_****.*****
         where *****_KW_GLAC = ' '
           and *****_KW_CAAC is not null) A
 where *****_end_date < *****_start_date

执行时报错:day of month must be between 1 and last day of month,但将查询条件改为*****_end_date > *****_start_date后,查询可正常执行无报错,请问问题原因是什么?

原因分析

核心问题是原始数据里存在非法日期数字,且这些非法值恰好出现在满足*****_end_date < *****_start_date的行中,具体拆解:

  • 你的转换逻辑是把数字按ddmmyy格式转成日期,但部分原始数字本身是无效的日期组合——比如像320122(对应32日01月2022),这种数字在调用to_date时,会直接触发“日期超出当月有效范围”的报错。
  • 数据库默认执行逻辑是先完成子查询中所有行的日期转换,再应用外层WHERE过滤。但当你把条件换成*****_end_date > *****_start_date时,数据库优化器可能做了谓词下推:把外层过滤条件提前到子查询阶段,先过滤掉不满足条件的行,再对剩下的行做日期转换。而那些包含非法日期的行恰好不满足>的条件,所以不会被执行转换,自然不会报错。
  • 当用*****_end_date < *****_start_date时,这些非法日期的行满足过滤条件,必须被转换,转换过程中因日期无效直接抛出错误。

说白了就是:你要查的“结束日期早于开始日期”的错误数据里,混了一批连日期格式都不合法的垃圾数据,转换时直接触发了报错;反过来查的时候,这些垃圾数据不在结果范围内,所以没触发报错。

内容的提问来源于stack exchange,提问作者berrin

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 22:10:09