Oracle 试图获取导致异常的实际数据

Oracle 试图获取导致异常的实际数据,oracle,exception,plsql,associative-array,Oracle,Exception,Plsql,Associative Array,我有一个过程,它接受两个关联数组的输入,在一些基本计数检查之后,执行FORALL语句将数据插入表中 程序如下: PROCEDURE INSERT_RECS(P_PROD_TYP IN prod_type, P_PROD_ADD_PK IN prod_pk_type) IS uniq_key EXCEPTION; PRAGMA EXCEPTION_INIT(uniq_key, -00001); loc_cnt NUM

我有一个过程,它接受两个关联数组的输入,在一些基本计数检查之后,执行FORALL语句将数据插入表中

程序如下:

    PROCEDURE   INSERT_RECS(P_PROD_TYP IN prod_type, P_PROD_ADD_PK IN prod_pk_type) 
        IS

        uniq_key EXCEPTION;
        PRAGMA EXCEPTION_INIT(uniq_key, -00001);
        loc_cnt  NUMBER;

        BEGIN
            IF P_PROD_TYP.COUNT = P_PROD_ADD_PK.COUNT THEN
               FORALL i IN P_PROD_TYP.FIRST .. P_PROD_TYP.LAST
                INSERT INTO product_table ( pk, 
                                            id,
                                            created_by,
                                            created_on,
                                            last_chg_by, 
                                            last_chg_on)
                                    VALUES (P_PROD_ADD_PK(i),
                                            P_PROD_TYP(i).id,
                                            P_PROD_TYP(i).created_by,
                                            P_PROD_TYP(i).created_on,
                                            NULL,
                                            NULL);

            END IF;
        EXCEPTION
            WHEN uniq_key THEN
                loc_cnt := SQL%BULK_EXCEPTIONS.count;
                FOR i IN 1 .. loc_cnt LOOP
                    dbms_output.put_line('EXCEPTION: Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
                            ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE) || 
                            ' SQLERRM: ' || SQLERRM || 
                            ' SQLCODE: ' || SQLCODE ||    
                            ' stack: ' || SYS.dbms_utility.format_call_stack);
                END LOOP;    
                RETURN;
        END;
CREATE OR REPLACE PROCEDURE PROC1 (V_EMP_ID DBMS_SQL.NUMBER_TABLE)
IS
     lv_error_string VARCHAR2(4000);
BEGIN
    FORALL INDX IN V_EMP_ID.FIRST..V_EMP_ID.LAST SAVE EXCEPTIONS
    UPDATE EMPLOYEES 
     ---trying to rasie an exception by using a calculation
    SET SALARY=SALARY * 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
    WHERE ID_E= V_EMP_ID(INDX);

EXCEPTION
    WHEN OTHERS 
    THEN
    FOR i IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
    LOOP
        ---Am printing the value of the exception array.
        dbms_output.put_line('exception Raised for record' ||V_EMP_ID(i));           

    END LOOP;
END;
/
我想要的是,如果我遇到异常,是否有一种方法可以查看导致问题的记录,基本上是关联数组中的索引,或者至少让SQL%info拥有该信息

我看了以下几点:


但这会输出关于列的信息,但这不是我想要的。

不确定是否真的回答了您的查询,但您可以使用异常块中的循环变量I来显示您案例中异常数组的内容。请参见下面的示例程序:

    PROCEDURE   INSERT_RECS(P_PROD_TYP IN prod_type, P_PROD_ADD_PK IN prod_pk_type) 
        IS

        uniq_key EXCEPTION;
        PRAGMA EXCEPTION_INIT(uniq_key, -00001);
        loc_cnt  NUMBER;

        BEGIN
            IF P_PROD_TYP.COUNT = P_PROD_ADD_PK.COUNT THEN
               FORALL i IN P_PROD_TYP.FIRST .. P_PROD_TYP.LAST
                INSERT INTO product_table ( pk, 
                                            id,
                                            created_by,
                                            created_on,
                                            last_chg_by, 
                                            last_chg_on)
                                    VALUES (P_PROD_ADD_PK(i),
                                            P_PROD_TYP(i).id,
                                            P_PROD_TYP(i).created_by,
                                            P_PROD_TYP(i).created_on,
                                            NULL,
                                            NULL);

            END IF;
        EXCEPTION
            WHEN uniq_key THEN
                loc_cnt := SQL%BULK_EXCEPTIONS.count;
                FOR i IN 1 .. loc_cnt LOOP
                    dbms_output.put_line('EXCEPTION: Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
                            ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE) || 
                            ' SQLERRM: ' || SQLERRM || 
                            ' SQLCODE: ' || SQLCODE ||    
                            ' stack: ' || SYS.dbms_utility.format_call_stack);
                END LOOP;    
                RETURN;
        END;
CREATE OR REPLACE PROCEDURE PROC1 (V_EMP_ID DBMS_SQL.NUMBER_TABLE)
IS
     lv_error_string VARCHAR2(4000);
BEGIN
    FORALL INDX IN V_EMP_ID.FIRST..V_EMP_ID.LAST SAVE EXCEPTIONS
    UPDATE EMPLOYEES 
     ---trying to rasie an exception by using a calculation
    SET SALARY=SALARY * 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
    WHERE ID_E= V_EMP_ID(INDX);

EXCEPTION
    WHEN OTHERS 
    THEN
    FOR i IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
    LOOP
        ---Am printing the value of the exception array.
        dbms_output.put_line('exception Raised for record' ||V_EMP_ID(i));           

    END LOOP;
END;
/
输出:

SQL> DECLARE
     empid   DBMS_SQL.NUMBER_TABLE;
    BEGIN
     empid (1) := 1;
     empid (2) := 9;

     PROC1 (empid);
   END;  

/
exception Raised for record  1

PL/SQL procedure successfully completed.

不确定是否真的回答了您的查询,但您可以使用异常块中的循环变量i来显示案例中异常数组的内容。请参见下面的示例程序:

    PROCEDURE   INSERT_RECS(P_PROD_TYP IN prod_type, P_PROD_ADD_PK IN prod_pk_type) 
        IS

        uniq_key EXCEPTION;
        PRAGMA EXCEPTION_INIT(uniq_key, -00001);
        loc_cnt  NUMBER;

        BEGIN
            IF P_PROD_TYP.COUNT = P_PROD_ADD_PK.COUNT THEN
               FORALL i IN P_PROD_TYP.FIRST .. P_PROD_TYP.LAST
                INSERT INTO product_table ( pk, 
                                            id,
                                            created_by,
                                            created_on,
                                            last_chg_by, 
                                            last_chg_on)
                                    VALUES (P_PROD_ADD_PK(i),
                                            P_PROD_TYP(i).id,
                                            P_PROD_TYP(i).created_by,
                                            P_PROD_TYP(i).created_on,
                                            NULL,
                                            NULL);

            END IF;
        EXCEPTION
            WHEN uniq_key THEN
                loc_cnt := SQL%BULK_EXCEPTIONS.count;
                FOR i IN 1 .. loc_cnt LOOP
                    dbms_output.put_line('EXCEPTION: Array Index: ' || SQL%BULK_EXCEPTIONS(i).error_index ||
                            ' Message: ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE) || 
                            ' SQLERRM: ' || SQLERRM || 
                            ' SQLCODE: ' || SQLCODE ||    
                            ' stack: ' || SYS.dbms_utility.format_call_stack);
                END LOOP;    
                RETURN;
        END;
CREATE OR REPLACE PROCEDURE PROC1 (V_EMP_ID DBMS_SQL.NUMBER_TABLE)
IS
     lv_error_string VARCHAR2(4000);
BEGIN
    FORALL INDX IN V_EMP_ID.FIRST..V_EMP_ID.LAST SAVE EXCEPTIONS
    UPDATE EMPLOYEES 
     ---trying to rasie an exception by using a calculation
    SET SALARY=SALARY * 99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999
    WHERE ID_E= V_EMP_ID(INDX);

EXCEPTION
    WHEN OTHERS 
    THEN
    FOR i IN 1 .. SQL%BULK_EXCEPTIONS.COUNT
    LOOP
        ---Am printing the value of the exception array.
        dbms_output.put_line('exception Raised for record' ||V_EMP_ID(i));           

    END LOOP;
END;
/
输出:

SQL> DECLARE
     empid   DBMS_SQL.NUMBER_TABLE;
    BEGIN
     empid (1) := 1;
     empid (2) := 9;

     PROC1 (empid);
   END;  

/
exception Raised for record  1

PL/SQL procedure successfully completed.

既然您有索引(SQL%BULK\u EXCEPTIONS(i).error\u index),为什么不直接循环p\u prod\u typ,直到找到导致错误的记录的索引?既然您有索引(SQL%BULK\u EXCEPTIONS(i).error\u index),为什么不在p_prod_typ中循环,直到找到导致错误的记录的索引?我对SQL%BULK_异常及其包含的行的理解是,它们只是异常,因此与表中的行(V_EMP_ID)之间不会有1对1的关系。不是这样吗?本质上,索引i很可能不等于索引INDX
SQL%BULK\u EXCEPTIONS
是一个隐式游标,它保存所有引发的异常。在例外块中,我们只是打印它。所以FORALL循环分别运行,异常分别阻止隐式游标循环。这就是示例中显示的内容。我正在传递一组数字,并在异常块中捕获异常。是的,在做了更多的研究之后,我看到了这种情况,非常感谢。我对SQL%BULK_异常及其包含的行的理解是,它们只是异常,因此与表中的行(V_EMP_ID)没有1对1的关系您正在论坛中迭代。不是这样吗?本质上,索引i很可能不等于索引INDX
SQL%BULK\u EXCEPTIONS
是一个隐式游标,它保存所有引发的异常。在例外块中,我们只是打印它。所以FORALL循环分别运行,异常分别阻止隐式游标循环。这就是示例中显示的内容。我正在传递一组数字,并在异常块中捕获异常。是的,在做了更多的研究之后,我看到了这种情况,非常感谢。