简体   繁体   English

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

[英]How to retrieve output parameter from stored procedure in oracle

I have below stored procedure. 我有下面的存储过程。 It works fine. 工作正常。 But I wanted to test it for error scenarios. 但是我想测试它的错误情况。 Even when there is an error, the procedure executes successfully without showing the error message. 即使出现错误,该过程也会成功执行,而不会显示错误消息。 When I enable the set serveroutput on, it shows the error message. 当我启用set serveroutput时,它显示错误消息。 But I want to capture the error message. 但是我想捕获错误消息。

    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;

You're using a nested block to throw your exception, but it will continue processing. 您正在使用嵌套块引发异常,但是它将继续处理。 The outbound variable "OUT_MESSAGE" should capture that value. 出站变量“ OUT_MESSAGE”应捕获该值。 Is it? 是吗? if so, you can see what it is with this: 如果是这样,您可以看到它的含义:

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;

If your program never throws an error, then OUT_MESSAGE will never be set, thus it will be null upon completion of the program. 如果您的程序从不抛出错误,则将永远不会设置OUT_MESSAGE,因此在程序完成时它将为null。

If you are looking to throw an error from your program if your "nested block" throws an error, then you need to re-raise the exception so that the outer exception catches it: 如果您希望在“嵌套块”引发错误的情况下从程序中引发错误,则需要重新引发异常,以便外部异常可以捕获该异常:

               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;

If you need the caller to raise an exception, you need that your procedure propagates it to the external. 如果需要调用方引发异常,则需要过程将其传播到外部。 For example: 例如:

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.

The first procedure will print a message and raise an exception; 第一个过程将打印一条消息并引发异常。 in this way, we have the error message in output and an exception: 这样,我们在输出中会显示错误消息和一个异常:

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

If you remove the RAISE , the exception will be handled and not propagated, thus giving no error: 如果删除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.

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM