在PLSQL中使用to_date的问题

问题描述 投票:0回答:2

我正在尝试将两个字段放在一起以使用case-when创建mm / dd / yyyy日期字段,并且它一直给我错误ORA-01722:无效的数字。

case when 
  extract(month from t.date) >= t.month 
  then to_date(t.month || '/' || '01' || '/' || extract(year from t.date), 'mm/dd/yyyy')
  else to_date(t.month || '/' || '01' || '/' || extract(year from t.date)-1, 'mm/dd/yyyy')
  end as effective_date
plsql plsqldeveloper
2个回答
0
投票

问题是Oracle应用连接运算符之前,它执行算术运算。因此,您的CASE语句的ELSE分支:

to_date(t.month || '/' || '01' || '/' || extract(year from t.date)-1, 'mm/dd/yyyy')

将执行类似'02/01/2019' - 1的操作。试图从一个字符串中减去一个(不重要的是,这是一个字符串而不是日期)不会导致ORA-01722。

您需要做的是将提取年份包装在某种东西中,以在连接之前强制减号运算。可以做到这一点:

to_date(t.month || '/' || '01' || '/' || to_char(extract(year from t.date)-1), 'mm/dd/yyyy')

0
投票

首先,@ APC提供的解决方案对于OP提出的问题是必要和充分的。但是,还有另一种选择。因为我对日期的字符串操作感到遗憾。将字符串转换为日期,然后使用日期函数(或根据需要添加时间戳)进行所有进一步处理。除最终显示或导出外,没有任何理由将日期转换为字符串。因此,我为以后的观众提供了以下替代方法。出现的问题分为以下几类:给定日期和目标月份-如果日期中的月份晚于目标月份,则返回目标月份中的第一个月。-如果日期的月份是目标月份的前一个,则返回上一年的目标月份的第一个。

alter session set nls_date_format = 'yyyy-mm-dd';
with t as (select to_date('02/11/20','mm/dd/rr') src_dte, 1 tgt_mon from dual union all
           select to_date('2020-02-11'),                  2         from dual union all
           select to_date('11-Feb-2020','dd-mon-yyyy'),   3         from dual
         )
select t.src_dte, tgt_mon
     , case when extract(month from t.src_dte) >= t.tgt_mon 
            then add_months(trunc(t.src_dte, 'year'), t.tgt_mon-1)
            else add_months(trunc(t.src_dte, 'year'), t.tgt_mon-1-12)
       end as effective_date
 from t;

如何运作。所有日期函数返回一个有效日期。1. trunc(src_date),'year')返回日期01-Jan-year2.从上面得到想要的月份只是添加必要的月份数(0-11)。由于目标是tgt_mon减去1,然后加到截断结果中,得出1-tgt_mon-year。3.对于上一年,请从上面获得相同的结果,然后减去1年(12个月)。没有减去月份的函数,因此只需加上-12。给出1-tgt_mon-year-1

我相信这是比日期处理中的字符串操作更好的方法,但这只是我的意见。考虑一下您是否愿意。

© www.soinside.com 2019 - 2024. All rights reserved.