PL / SQL函数和异常

时间:2014-08-01 16:20:08

标签: sql plsql oracle11g oracle-sqldeveloper

我是PL / SQL的新手,我正在编写一个有点复杂的脚本。为了使脚本更清洁,我想创建许多功能。但是我对功能不太熟悉。 一个函数可以有VOID返回类型吗?如果我必须返回,它将如何处理异常处理? 见下文:

EX:

DECLARE

  some_variable NUMBER;

  FUNCTION myFunc1(pInput IN NUMBER) RETURN NUMBER
  IS
  BEGIN
    -- DO SOMETHING
  EXCEPTION
  WHEN someException THEN
    DBMS_OUTPUT.PUT_LINE('ERROR someException ');
  WHEN Others THEN
    DBMS_OUTPUT.PUT_LINE('ERROR');
  -----------------------------
  -- WHERE DO I PUT THE RETURN?
  -----------------------------
  END;

  FUNCTION myFunc2(pInput IN NUMBER) -- CAN IT RETURN NOTH
  IS
    fun1Return NUMBER;
  BEGIN
    -- DO SOMETHING
    fun1Return  := myFunc1(1);
  EXCEPTION
  WHEN someException THEN
    DBMS_OUTPUT.PUT_LINE('ERROR someException ');
  WHEN Others THEN
    DBMS_OUTPUT.PUT_LINE('ERROR');
  END;



BEGIN
  --- DO SOMETHING
  some_variable := myFunc2(2);


EXCEPTION
WHEN someException THEN
  DBMS_OUTPUT.PUT_LINE('ERROR someException ');
WHEN Others THEN
  DBMS_OUTPUT.PUT_LINE('ERROR');

END;

1 个答案:

答案 0 :(得分:2)

很好地涵盖了in the documentation

函数必须在异常处理程序之前返回(如果有的话)。但是在你的例子中,你不应该真正捕捉异常,因为你只是压缩错误,并且你假设无论谁调用它都能看到dbms_output这不是一个安全的假设。如果你没有重新提升(或任何)异常,那么你仍然需要从异常处理程序以及块的主体返回:

  FUNCTION myFunc1(pInput IN NUMBER) RETURN NUMBER
  IS
  BEGIN
    -- DO SOMETHING
    RETURN 0;
  EXCEPTION
  WHEN someException THEN
    DBMS_OUTPUT.PUT_LINE('ERROR ' || SQLERRM);  
    -- how do you know where the exception was raised?
    RETURN -1;
  WHEN Others THEN
    DBMS_OUTPUT.PUT_LINE('ERROR');
    -- how does the caller know what went wrong?
    RETURN -2;
  END;

您还隐藏了错误的所有细节,并消除了能够找出实际出错的希望。捕捉when others特别邪恶,特别是如果你不重新提出异常。如果你真的想要显示你自己的消息,你仍然应该重新提出原始异常,在这种情况下你不会再需要返回:

  FUNCTION myFunc1(pInput IN NUMBER) RETURN NUMBER
  IS
  BEGIN
    -- DO SOMETHING
    RETURN 0;
  EXCEPTION
  WHEN someException THEN
    DBMS_OUTPUT.PUT_LINE('ERROR ' || SQLERRM);
    RAISE;
  WHEN Others THEN
    DBMS_OUTPUT.PUT_LINE('ERROR');
    RAISE;
  END;

哪个稍好一些,但您仍然会丢失有关错误堆栈的一些信息。你可能根本不想抓住这些:

  FUNCTION myFunc1(pInput IN NUMBER) RETURN NUMBER
  IS
  BEGIN
    -- DO SOMETHING
    RETURN 0;
  END;

真正捕捉异常的唯一原因是,如果它是你期望的并且可以优雅地处理。其他任何事情 - 尤其是 other - 几乎总是更好地向左传播调用堆栈。

如果你的功能中有分支,你也可以有多个回报。

  FUNCTION myFunc1(pInput IN NUMBER) RETURN NUMBER
  IS
  BEGIN
    IF SOMETHING THEN
      RETURN 1;
    END IF;
    RETURN 0;
  END;

正如@couling所说,一个没有回报的功能就是一个程序。再次剥离异常:

  PROCEDURE myProc2(pInput IN NUMBER)
  IS
    fun1Return NUMBER;
  BEGIN
    -- DO SOMETHING
    fun1Return  := myFunc1(1);
  END;