plsql - oracle add_months 添加额外的日期

haj*_*aju 2 oracle plsql

甲骨文: 12c

描述:尝试使用 add_months 将 99 年添加到日期中,该方法可以工作,但是它会在返回日期值中添加额外的一天。我应该如何正确添加日期的年份?

declare 
  toRetDate DATE;
  inputDate DATE;
  numYears number;
begin

  numYears := 99;
  inputDate := TO_DATE('28-FEB-85', 'DD-Mon-YY' );
  toRetDate := add_months(inputDate, numYears*12);
  DBMS_OUTPUT.put_line(toRetDate);
end;
Run Code Online (Sandbox Code Playgroud)

输出:29-FEB-84

小智 5

ADD_MONTHS 不会在结果中添加一天。相反,它具有这个非常普遍的功能:如果您将月份添加到日期,并且该日期是该特定月份/年份的月底,则 ADD_MONTHS 的结果是结果月份的最后一天。

例如,如果您在 1 月 31 日上添加一个月,则始终会得到 2 月 28 日(或闰年的 2 月 29 日)。如果将 6 月 30 日加一个月,则得到 7 月 31 日。

如果你在 2 月 28 日加上一个月,你就会得到 3 月 31 日,除非它是闰年;在闰年中,2 月 28 日不是该月的最后一天,因此如果加上一个月,就会得到 3 月 28 日。

在所有情况下,如果结果的天数大于结果月份的天数,则结果只是该月的最后一天。

编辑:在这个答案下面的评论中,OP询问是否有办法保持该月的同一天,除了2月29日(在非闰年应该成为2月28日)。

答案是肯定的。正如 @Xing 在另一个答案中所示,添加interval '99' year将保留日期,但当输入日期为 2 月 29 日且结果年份不是闰年时,可能会导致麻烦。这可以通过初步检查来解决。可以使用 IF 语句或 CASE 表达式来完成。我更喜欢后者,因为它在 PL/SQL 和 SQL 中的工作原理相同;普通 SQL 中没有 IF。

toretdate := case when to_char(inputdate, 'mm-dd') = '02-29'
                  then (inputdate + 1) + interval '99' year - 1
                  else inputdate + interval '99' year end
Run Code Online (Sandbox Code Playgroud)

诀窍是,当inputdate2 月 29 日时,将其向前推进一天,使其成为 3 月 1 日,然后添加 99 年(仍然是 3 月 1 日),然后减去一天,使其成为 2 月 29 日(如果是闰年)或2 月 28 日(其他时间)。