尝试在 SQL 查询中输入 0 到 11 之间的月份时出现 oracle 错误 ORA-01843
oracle error ORA-01843 when trying to enter months between 0 to 11 in SQL Query
我正在使用以下函数,它采用三个参数日期、要添加的年份和要添加的月份以及 returns 最终日期。
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;
当您执行 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 月结束,提取物会给你 10,再次给你一个有效的月份)。
所有其他日期和调整组合都发生了同样的事情。您也会遇到与日期编号类似的问题。
您可以将提取的数字左填充到两个字符,但这样做会简单得多:
return add_months(p_date, (p_years * 12) + p_months);
或者根本不使用您自己的函数,因为这样做并不比调用函数多多少工作。
我正在使用以下函数,它采用三个参数日期、要添加的年份和要添加的月份以及 returns 最终日期。
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;
当您执行 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 月结束,提取物会给你 10,再次给你一个有效的月份)。
所有其他日期和调整组合都发生了同样的事情。您也会遇到与日期编号类似的问题。
您可以将提取的数字左填充到两个字符,但这样做会简单得多:
return add_months(p_date, (p_years * 12) + p_months);
或者根本不使用您自己的函数,因为这样做并不比调用函数多多少工作。