Oracle PL / SQL从具有OUT变量的过程返回

时间:2016-11-28 13:11:04

标签: oracle plsql

是否可以使用带有OUT变量的PL / SQL过程作为返回码而不是Raise_Application_Error,而不是使用大量嵌套if / then?

示例:

Create or replace procedure myProc (
  ID in number
  ..
  ,message out varchar2
) as
..
BEGIN
  if not ( myCheck1 ) then
    message := 'Unsuccessful check1';
    return; -- !!! using return here causes message is empty :-( 
  end if;

  some code goes here;

  if not ( myCheck2 ) then
    message := 'Unsuccessful check2';
    return; -- !!! using return here causes message is empty :-( 
  end if;

  not deeply nested code goes here;

END;

当然可以使用if / else实现请求的输出, 但是当使用多个嵌套检查时,代码很难读, 因为长嵌套的if / else结构,如下例所示:

..
BEGIN
  if not ( myCheck1 ) then
    message := 'Unsuccessful check1';
  else
    ..
    if not ( myCheck2 ) then
      message := 'Unsuccessful check2';
    else
      ..
      ..
      if not ( myCheck3 ) then
        message := 'Unsuccessful check3';
      else
        ..
        deeply nested code goes here; -- :-(
      end if; -- end of check3
    end if; -- ned of check2
  end if; -- end of check1
END;


declare
  message  varchar2(100);
Begin
  myProc (
  '123' -- ID
  ..
  ,message
  );
  dbms_output.put_line( message ); -- any output here when using RETURN statement :-(
END;
/

2 个答案:

答案 0 :(得分:1)

我会使用用户定义的异常实现您的第一种方法。这些允许我们将定制的异常整齐地引入标准异常处理部分。这至少使代码更容易理解。此外,引发异常是惯用的PL / SQL,而在您显示的方式中使用return与使用goto语句完全相同,只是不太诚实:)

Create or replace procedure myProc (
  ID in number
  ..
  ,message out varchar2
) as
..
  x_check_1 exception;
  x_check_2 exception;
BEGIN
  if not ( myCheck1 ) then
    raise x_check_1;
  end if;

  some code goes here;

  if not ( myCheck2 ) then
       raise x_check_2;
  end if;

  not deeply nested code goes here;
EXCEPTION
    when x_check_1 then
        message := 'Unsuccessful check1';
    when x_check_2 then
        message := 'Unsuccessful check2';
END;

一般来说,使用OUT参数传递状态代码或消息并不是一种好习惯:它们太容易被忽略。我们可以将用户定义的例外与预留范围-20999-20000中的数字相关联。因此,我们可以提出定制的例外情况,并将处理它们的责任提升到调用程序。

Create or replace procedure myProc (
  ID in number
  ..
) as
..
  x_check_1 exception;
  pragma exception_init(x_check_1, -20000);
  x_check_2 exception;
  pragma exception_init(x_check_2, -20001);
BEGIN
  if not ( myCheck1 ) then
    raise x_check_1;
  end if;
  ...

答案 1 :(得分:0)

你可以使用raise_application_error但是然后抓住它并转移到out param。

procedure p(param out varchar2)
begin
--logic with raise_application_error and exceptions thrown
exception when others then
param := --what you need to return in out
end;
/