【问题标题】:PL/SQL Function returns ORA-06503: PL/SQL: Function returned without valuePL/SQL 函数返回 ORA-06503: PL/SQL: 函数返回无值
【发布时间】:2013-05-06 11:50:45
【问题描述】:

我必须编写一个 pl/sql 代码(实际上是一个函数),它在将郊区作为参数时返回一个邮政编码 代码是这样的:

create or replace 
FUNCTION get_postCode(p_suburb IN varchar2)
RETURN varchar2 
IS
--
v_postcode varchar2;
--
CURSOR c1 IS 
SELECT locality, postcode FROM table_postcode;
--
BEGIN
--
FOR r1 IN c1 
loop
    IF upper(r1.locality) = upper(p_suburb)
    THEN 
      v_postcode := r1.postcode;
      return v_postcode;
    END IF;
exit WHEN c1%notfound;
END loop;
-- return v_postcode;
--
exception WHEN others then
v_postcode := null;  
END; 

table_postcode 是从 Post Office 获得的,它包含郊区(作为表格中的列)和邮政编码以及与此案例无关的其他字段。

当我使用该函数时,它返回正确的值,当我将这个函数用作 SELECT 子句的列时,它仅在我不在 FROM 子句之后添加任何其他子句时才返回。这对我来说很奇怪。

情况是:

select street, suburb, get_postcode(suburb) from my_table;

上面的行给了我结果,但是

select street, subur, get_postcode(suburb) from my_table order by suburb;

失败并给我以下错误消息:

ORA-06503: PL/SQL: Function returned without value
ORA-06512: at "U11254683.GET_POSTCODE", line 25
06503. 00000 -  "PL/SQL: Function returned without value"
*Cause:    A call to PL/SQL function completed, but no RETURN statement was
       executed.
*Action:   Rewrite PL/SQL function, making sure that it always returns
       a value of a proper type.

如果我在这样的块中调用函数:

Declare
v_post varchar2(10);
Begin
v_post := get_postcode('Sydney');
DBMS_OUTPUT.PUT_LINE('The post code is '||v_post);
End;

结果是正确的,给了我 2000。

【问题讨论】:

  • 你为什么要使用光标?
  • 遍历表格并检查郊区匹配并获取邮政编码,我做错了吗?或者...
  • 简短回答:是的 - SQL 是一种基于集合的语言,最适合用于基于集合的操作。有关使用函数的更好方法,请参阅 hol 的答案。
  • 谢谢,给初学者的好课

标签: sql database oracle select plsql


【解决方案1】:

当什么都没找到时,你应该返回一些东西。声明中exception之前的评论

return v_postcode;

您的例程的编写方式可能没有找到任何内容,然后到达函数末尾而不返回任何内容,因此出现错误“函数返回没有值”。确实是这样。

但是,您可以通过直接选择郊区来更轻松地完成此操作。但是,如果您有多个邮编到郊区(如果可能的话),您会怎么做?

create or replace FUNCTION get_postCode(i_suburb IN varchar2)
RETURN varchar2 
IS
  l_postcode varchar2;
BEGIN
  select postcode 
    into l_postcode
   where upper(i_suburb) = upper(locality);
-- 
  return l_postcode;
exception 
  WHEN others then
    return null;  
END; 

在此版本中,如果一个郊区存在于多个邮政编码中,您将得到 null。现在由您的设计决定如何处理这种情况。然后你可以在异常中处理它

exception
   when TOO_MANY_ROWS then
        return '**Error** Several Values'; -- do something meaningful here 
   when NO_DATA_FOUND then
        return null; -- if you want to return null on nothing found

【讨论】:

  • 感谢您的建议。我已经尝试了您的代码,并且确实遇到了太多行错误的问题,现在正在例外处理
  • @DilshatAbduwalli:别对我们大喊大叫
  • @a_horse_with_no_name 我也是这么想的,但不是每个人都知道大写的意思是叫喊。在这种情况下,我将其解释为不是大喊大叫。实际上是否有一个 Stackoverflow 规则,大写意味着大喊,或者这是来自一般网络种族?
  • @hol:据我所知,在任何“在线”对话(论坛、邮件、新闻组……)中,大写字母都被认为是喊叫。
  • @a_horse_with_no_name 据我所知,但不止一次我观察到这不是(更多)常识:-) 从那时起我根据上下文解释它的好坏。
【解决方案2】:

试试这个:

CREATE OR REPLACE FUNCTION get_postCode
(p_suburb IN varchar2)
RETURN varchar2 
IS
    v_postcode varchar2;
    CURSOR c1 IS 
        SELECT locality, postcode FROM table_postcode;
BEGIN
    FOR r1 IN c1 LOOP
        EXIT WHEN c1%notfound;
        IF upper(r1.locality) = upper(p_suburb) THEN 
          v_postcode := r1.postcode;
          EXIT;
        END IF;
    END LOOP;
    return v_postcode;
    exception WHEN others then
    return null;  
END; 
/

通过在找出第一个邮政编码时退出FOR 循环,您可以确保没有引发TOO_MANY_ROWS 异常。此外,通过将return 放在IF 语句之外,您可以确保在找不到任何内容时至少返回一个NULL

【讨论】:

  • 在你的代码中它仍然不起作用,因为在异常之后它不会返回到代码(它得到异常的地方)并且仍然没有return语句被命中。
  • 好吧,类似的代码在我的机器上非常适合我! :D
  • 我的意思是如果发生任何异常(现在不太可能是如何编码的),它将进入异常,然后不返回任何内容。
  • @hol:是的,你是对的。我应该在异常块中放一个return null。编辑。
  • 不过,我相信我现在不太可能得到NO_DATA_FOUNDTOO_MANY_ROWS 异常。
猜你喜欢
  • 1970-01-01
  • 2013-02-26
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 1970-01-01
  • 2016-12-27
  • 2012-10-31
相关资源
最近更新 更多