0

我正在使用以下函数,它需要三个参数日期、要添加的年份和要添加的月份,并返回最终日期。

    create or replace function date_add_year_month(p_date in date, p_years in number, p_months in number)
return date

as
v_years number;

v_date date;
begin
v_date := add_months(p_date, p_months);
v_years := p_years + extract(year from v_date);
return  to_date(v_years || (extract(month from v_date)) || (extract (day from v_date)), 'YYYYMMDD');
end;
/

现在,如果我运行以下测试数据,我会收到无效月份的错误。

 select date_add_year_month(date '2009-10-28', 0, 10) from dual;
    select date_add_year_month(date '2009-10-28', 0, 11) from dual;
    select date_add_year_month('2009-Jan-01', 5, 0) from dual;
    select date_add_year_month(date '2009-Oct-28', -1, -5) from dual;

但是一旦我开始在函数中输入月份值 12 或以上,它就会开始给我一个输出。

select date_add_year_month(date '2009-10-28', 0, 12) from dual;
select date_add_year_month(date '2009-10-28', 0, 13) from dual;
select date_add_year_month(date '2009-Oct-28', 1, 26) from dual;
select date_add_year_month(date '2009-10-28', 0, 36) from dual;
select date_add_year_month(date '2009-10-28', -1, 26) from dual;
4

1 回答 1

0

当你这样做时extract (month from v_date),结果是一个数字,可能是一个数字。将 10 个月添加到 2009-10-28 会得到 2010-08-28,然后从中提取月份数会得到 8 - 而不是08。在这种情况下,您将添加零年,因此您最终尝试这样做:

to_date(v_years || (extract(month from v_date)) || (extract (day from v_date)), 'YYYYMMDD')

变成:

to_date(2009 || 8 || 28), 'YYYYMMDD')

也就是说,在隐式转换为字符串之后:

to_date('2009828', 'YYYYMMDD')

...并且 82 不是有效的月份数。当您经过 11 个月时,您将得到 92。当您经过 12 个月时,虽然您回到 10 月,但提取得到 10,并且您回到字符串中正确数量的字符 - 匹配您的格式模型。(如果你在 11 月通过了一个日期,那么 11 个月就可以了,因为它仍然会在 10 月结束,并且 extract 会给你 10,再次给你一个有效的月份)。

所有其他日期和调整组合都会发生同样的事情。您也可以在日期编号方面遇到类似的问题。

您可以将提取的数字左填充为两个字符,但这样做会更简单:

return add_months(p_date, (p_years * 12) + p_months);

或者根本不使用你自己的函数,因为这样做并不比调用函数多多少。

于 2015-02-06T00:02:42.647 回答