无法引发应用程序错误消息

时间:2011-11-11 18:00:29

标签: oracle error-handling plsql oracle11g

出于调试目的,我需要根据给定的标志引发应用程序级别的消息。这是异常代码

  EXCEPTION
    WHEN dml_errors THEN
      l_errors := SQL%BULK_EXCEPTIONS.COUNT;
      S_Publish('I', 'Number of statements that failed: ' || l_errors);
      FOR i IN 1..l_errors LOOP
         S_Publish('I', 'Error #' || TO_CHAR(i) || ' occurred during '|| 'iteration #' || SQL%BULK_EXCEPTIONS(i).ERROR_INDEX);
         S_Publish('I', 'Error message is ' || SQLERRM(-SQL%BULK_EXCEPTIONS(i).ERROR_CODE));
         S_Publish('I', 'Failing Record ID is ' || sap_tbl_ins(SQL%BULK_EXCEPTIONS(i).ERROR_INDEX).DEVICE_PIN);
      END LOOP;
      IF g_app_error_flag THEN
        raise_application_error(-20707, 'Fatal Error: Replication script exceptions', TRUE);
      END IF;

    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE('Error on record:' || l_zzman);
      S_Publish('I', 'SAP_EQUI Update: Failure processing record ' || l_zzman);
      S_Publish ('F');
      IF g_app_error_flag THEN
        raise_application_error(-20708, 'Fatal Error: Replication script exceptions', TRUE);
      END IF;

现在给出这个代码,只要** g_app_error_flag为真, raise_application_error 就会引发一个。但是,在所有情况下(我的意思是测试环境,我通过在表格上添加一些约束来故意使脚本失败),我所看到的只是DML错误,即

ORA-01403: no data found 
ORA-06512: at "DBNAME.PRODUCT_COPY_PACKAGE", line 1808 
ORA-24381: error(s) in array DML 
ORA-06512: at "DBNAME.PRODUCT_COPY_PACKAGE", line 84 
ORA-06512: at line 3 

你们可以建议一下吗?

P.S:

这是S_Publish的定义。 S_Publish中没有“加注”。

  PROCEDURE S_Publish (i_type IN VARCHAR2, 
                         i_msg IN VARCHAR2 DEFAULT NULL) IS
  BEGIN

    CASE

       WHEN i_type = 'G' THEN
         IF g_debug_flag
         THEN
           INSERT INTO logtable (tstamp,line) values (SYSDATE, i_msg);
           COMMIT;
           g_counter := 0;
         END IF;

       WHEN i_type = 'F' THEN
         g_err_code  := SQLCODE;
         g_err_msg   := TO_CHAR(g_err_code)||' '||SUBSTR(SQLERRM, 1, 100);
         INSERT INTO logtable (tstamp,line) values (SYSDATE, g_err_msg);
         COMMIT;

       WHEN i_type = 'I' THEN
         INSERT INTO logtable (tstamp,line) values (SYSDATE, i_msg);
         COMMIT;
         g_counter := 0;

    END CASE;


  END S_Publish;

经过一些调试后,到目前为止我已经想到了什么。我不知道它背后是什么呢?

所以问题是程序在结束打印错误即FOR i IN 1..l_errors LOOP之后就会退出。该程序退出END LOOP。为什么之后的任何事情都没有被执行?

3 个答案:

答案 0 :(得分:2)

所以问题发生在S_Publish。它所指的表格,即sap_tbl_ins是基于0的。 SQL%BULK_EXCEPTIONS(i).ERROR_INDEX基本上是失败时的迭代次数。因此,引用一个基于0的索引和一个数字会引发数组超出范围"例外。我只想出来并将公式改为

S_Publish('I', 'Failing Record ID is ' || sap_tbl_ins((SQL%BULK_EXCEPTIONS(i).ERROR_INDEX)-1).DEVICE_PIN);

并且工作正常。

答案 1 :(得分:0)

由于我们没有看到所有代码,我们必须依赖于您,当您通过在表上添加一些约束来故意执行脚本失败时,您发布的此异常块就是活性。因此,如果此块正在生效,您没有看到“raise_application_error(-20707,.....”或带有-20708的第二个)的原因可能是“S_Publish”过程本身引发异常除非你用额外的一个来包围它们,否则不会在它们运行的​​同一个异常块中捕获。为了测试这个理论,尝试暂时删除对它的调用,看看你是否得到了引发的错误。

答案 2 :(得分:0)

好的,问题:

1)PRODUCT_COPY_PKG中第1808行/周围的代码是什么。这是第一个错误发生的地方。

2)插入到logtable是否正在发生? (即 - 这个异常块是否真的在执行?)

3)那个错误堆栈输出是否来自dbms_output语句?或者是Oracle在运行时的堆栈转储?

样式注释:我希望用PRAGMA AUTONOMOUS_TRANSACTION定义S_PUBLISH,否则你的COMMIT可以提交一个部分完成的事务,如果你的代码在出错的时候正在做的事情......