如何从oracle中的存储过程中检索输出参数

时间:2016-10-12 14:53:34

标签: oracle stored-procedures oracle11g

我有以下存储过程。它工作正常。但我想测试它的错误情况。即使出现错误,该过程也会成功执行,而不会显示错误消息。当我启用set serveroutput时,它会显示错误消息。但我想捕获错误消息。

    create or replace PROCEDURE         COMP_JSON (
    OUT_MESSAGE                 OUT  VARCHAR2,
    PNI_ID                      IN   NUMBER
)
 AS

    CURSOR C1 IS SELECT 1  AS ID,TYPE_ID, COMP, TYPE, PREV_AMOUNT, CURR_AMOUNT FROM V_COMP_COST;

    SECID VARCHAR2(100);    

    K NUMBER:= 0;
    L NUMBER:= 1000;--Commit Interval

    LRETVALUE VARCHAR2(200):='0';

    V_TYPE_ID      JSON_DATA.TYPE_ID%TYPE;
    V_COMP         JSON_DATA.COMP%TYPE; 
    V_TYPE         JSON_DATA.TYPE%TYPE;  


BEGIN

    APEX_JSON.INITIALIZE_CLOB_OUTPUT;

/* Cost Comparison */
    IF NVL(PNI_ID, 1) = 1
    THEN

        K := 0;

        BEGIN
            FOR I IN C1 
            LOOP 
                  V_TYPE_ID := I.TYPE_ID;
                  V_COMP := I.COMP; 
                  V_TYPE := I.TYPE;  

                  APEX_JSON.OPEN_OBJECT;
                  APEX_JSON.WRITE('prevAmt',I.PREV_AMOUNT);      
                  APEX_JSON.WRITE('currAmt',I.CURR_AMOUNT);      
                  APEX_JSON.CLOSE_OBJECT;

                  INSERT INTO JSON_DATA 
                  VALUES (I.ID,I.TYPE_ID,I.COMP,I.TYPE,APEX_JSON.GET_CLOB_OUTPUT);      
                  /* Commit Interval  */
                  K := K+1;

                  IF MOD(K,L) = 0 
                  THEN 
                      COMMIT;
                  END IF;

                  APEX_JSON.FREE_OUTPUT;

                  IF K > 5
                  THEN 
                      RAISE_APPLICATION_ERROR(-20000, NULL);
                  END IF;
            END LOOP;

        EXCEPTION
            WHEN OTHERS 
            THEN LRETVALUE := '-1,k:Problem in loading Data -' || SQLERRM  || ' AT: [' || V_TYPE_ID || '] [' || V_COMP || '] [' || V_TYPE || ']';
        END;

        COMMIT;

        IF LRETVALUE <> '0'
        THEN
           OUT_MESSAGE := LRETVALUE;
            RETURN;
        END IF;
    END IF;

EXCEPTION
WHEN OTHERS
THEN DBMS_OUTPUT.PUT_LINE('ERROR MESSAGE' || SQLERRM);

END COMP_JSON;

2 个答案:

答案 0 :(得分:1)

您正在使用嵌套块来抛出异常,但它会继续处理。出站变量&#34; OUT_MESSAGE&#34;应该捕获这个价值。是吗?如果是这样,你可以看到它是什么:

SQL> VAR ERR_MSG VARCHAR2;
SQL> EXEC COMP_JSON(:ERR_MSG, 5);  --whatever you use for PNI_ID....

PL/SQL procedure successfully completed.

SQL> PRINT ERR_MSG;

如果您的程序从不抛出错误,则永远不会设置OUT_MESSAGE,因此在程序完成后它将为null。

如果您想要从您的程序中抛出错误,如果您的&#34;嵌套块&#34;抛出一个错误,然后你需要重新引发异常,以便外部异常捕获它:

               IF K > 5
                      THEN 
                          RAISE_APPLICATION_ERROR(-20000, NULL);
                      END IF;
                END LOOP;
    EXCEPTION
        WHEN OTHERS THEN 
            LRETVALUE := '-1,k:Problem in loading Data -' || SQLERRM  || ' AT: [' || V_TYPE_`ID || '] [' || V_COMP || '] [' || V_TYPE || ']';
            RAISE_APPLICATION_ERROR(-20000, LRETVALUE );
    END;

答案 1 :(得分:0)

如果您需要调用者引发异常,则需要将您的过程传播到外部。 例如:

SQL> create or replace procedure raiseException(p in number) is
  2      n number;
  3  begin
  4      n := p/0;
  5  exception
  6      when others then
  7          dbms_output.put_line('Error message: ' || sqlerrm);
  8          raise;
  9  end;
 10  /

Procedure created.

SQL> create or replace procedure procedureCall is
  2  begin
  3      raiseException(10);
  4  end;
  5  /

Procedure created.

第一个程序将打印一条消息并引发异常;通过这种方式,我们在输出中有错误消息和异常:

SQL> exec procedureCall
Error message: ORA-01476: divisor is equal to zero
BEGIN procedureCall; END;

*
ERROR at line 1:
ORA-01476: divisor is equal to zero
ORA-06512: at "ALEK.RAISEEXCEPTION", line 8
ORA-06512: at "ALEK.PROCEDURECALL", line 3
ORA-06512: at line 1

如果删除RAISE,则会处理异常并且不会传播,因此不会出错:

SQL> create or replace procedure raiseException(p in number) is
  2      n number;
  3  begin
  4      n := p/0;
  5  exception
  6      when others then
  7          dbms_output.put_line('Error message: ' || sqlerrm);
  8  end;
  9  /

Procedure created.

SQL> exec procedureCall
Error message: ORA-01476: divisor is equal to zero

PL/SQL procedure successfully completed.