Sql 指定月份的日期无效-ORA-01839

Sql 指定月份的日期无效-ORA-01839,sql,oracle,function,Sql,Oracle,Function,如果输入错误的日期,是否可以在函数put EXECOPTION内避免错误 Select F_RETURN_DAY_NAME(2021,6,30) from dual; --WORK (Jun have 30 days) Select F_RETURN_DAY_NAME(2021,6,31) from dual; --DONT WORK create or replace Function F_RETURN_DAY_NAME ( p_year

如果输入错误的日期,是否可以在函数put EXECOPTION内避免错误

Select F_RETURN_DAY_NAME(2021,6,30) from dual;     --WORK (Jun have 30 days)
Select F_RETURN_DAY_NAME(2021,6,31) from dual;     --DONT WORK



create or replace Function F_RETURN_DAY_NAME
       ( 
         p_year IN number,
         p_month IN number,
         p_day IN number
       )
       RETURN varchar2
    IS
       v_return varchar2(100);
    
    BEGIN
    
         return substr(to_char(TO_DATE(p_year || '-' || p_month || '-' || p_day, 'YYYY-MM-DD'),'DY'),0,3) ; 
    
    END;

由于您使用的是最新版本,因此可以使用
默认值。。。转换错误时

其中包括:

Select F_RETURN_DAY_NAME(2021,6,30) from dual;

F_RETURN_DAY_NAME(2021,6,30)
----------------------------
WED

我已经删除了您没有使用的局部变量;子字符串-DY给出了日期的缩写名称。在英语中,无论如何都是三个字符;在其他语言中,它可以更长,但为了避免歧义,只使用前三个字符会引起混淆。如果要确保无论用户的会话设置如何,日期缩写始终是一种特定语言,则可以向
to_char()
提供另一个参数:


值得关注的是,函数也可能在null输入上被调用,这不是无效的;在这种情况下,函数确实应该返回null(这里是猜测,但我认为这是大多数用例所需要的),而不是返回“错误的日期”

在尝试转换之前,可以检查所有值是否为空:

...
  if p_year is null and p_month is null and p_day is null then
    return null;
  end if;

  return coalesce(
...


您需要决定如何只处理一个或两个空参数;此时(或第13个月,或第10000年)都将返回“错误的一天”。如果希望任何null参数返回null,则执行相同的操作,但使用“or”而不是“and”。您可能需要一个更通用的错误返回值-“无效日期”,例如,我在最新的Fiddle中使用了该值。

您使用的是哪一版本的Oracle?(如果不确定,则查询v$版本)。好的,您已经更新了问题,从需要默认值更改为异常值;但是它已经抛出了一个异常-那么您希望发生什么呢?这是有可能的,或者(正如Alex Poole所建议的,如果您的Oracle版本足够高),使用默认的转换错误选项到
to_date
,或者如果您的版本较旧,您可以在嵌套块中进行计算,并在其中捕获和处理错误-然后在处理错误后,控制返回到主块。@AlexPoole版本19,如果没有重新结果返回,例如,v中的“错误日期”。@AlexPoole版本19_return@mathguy我不知道有没有可能用简单的方法解决这个问题,我有3个参数,需要从day name中获取前3个字符。当然,你不知道这是否可能,这就是为什么你在这里问这个问题。亚历克斯已经向你展示了一种简单的方法。现在,你还有一个问题:例如,如果月份错了怎么办?一个月14英镑?Alex的解决方案仍然会报告“错误的一天”,而事实上错误的是月份。这是个问题吗?使用一些虚构的日期作为默认日期,并使用稍微复杂一点的
大小写
表达式返回
“错误的日期”
,不是更好吗?值得关注的是,该函数也可能在
null
输入上被调用,这不是无效的;在这种情况下,函数确实应该返回
null
(这里是猜测,但我认为这是大多数用例所需要的),而不是返回
“错误的一天”
。也许吧,但是您使用的是一个神奇的值,这也不是很好。如果拥有所有空组件是有效的,那么可以在尝试转换之前检查它。事实上,最好先检查空组件。在任何情况下,我意识到还有其他潜在的问题——我只是问OP如果提供了错误的月份,而不是错误的月份日期,会发生什么。那么,在嵌套块中处理可能会更方便,即使在新版本中有默认的on错误。
Select F_RETURN_DAY_NAME(2021,6,31) from dual;

F_RETURN_DAY_NAME(2021,6,31)
----------------------------
Wrong day
  return coalesce(
    to_char(to_date(p_year || '-' || p_month || '-' || p_day
      default null on conversion error, 'YYYY-MM-DD'),
      'DY',
      'NLS_DATE_LANGUAGE=ENGLISH'),
    'Wrong day') ; 
...
  if p_year is null and p_month is null and p_day is null then
    return null;
  end if;

  return coalesce(
...