在存储过程中的 PL/SQL 或 SQL Oracle Developer 中引发异常

Raising an Exception in PL/SQL or SQL Oracle Developer within a Stored Procedure

我正在尝试处理 SQLPLUS 中的自定义异常,我有两个存储过程,第二个存储过程调用第一个。

在第一个存储过程中,我有一个检查 table 中行的 data_types 的 CASE,如果类型不是 CHAR、VARCHAR2、DATE 或 NUMBER,然后它应该显示我在调用第一个过程的第二个过程中声明的客户异常的 Data_Type 和 RAISE_APPLICATION_ERROR。

这是我在第二个存储过程中的代码:

 CASE CurrentRow.Data_Type 
      WHEN 'CHAR' THEN
      wDataType := (CurrentRow.Data_Type || '(' || CurrentRow.CHAR_LENGTH || ')');      
      WHEN 'VARCHAR2' THEN
      wDataType := (CurrentRow.Data_Type || '(' || CurrentRow.CHAR_LENGTH || ')');
      WHEN 'DATE' THEN
      wDataType := (CurrentRow.Data_Type);
      WHEN 'NUMBER' THEN
      wDataType := (CurrentRow.Data_Type || '(' || CurrentRow.Data_Precision || ',' || CurrentRow.Data_Scale || ')');
    ELSE
      wDataType := (CurrentRow.Data_Type);
      RAISE_APPLICATION_ERROR(-20100, '*** Unknown Data Type ' || CurrentRow.Data_Type || ' ***');      
    END CASE;

现在我的第二个存储过程中有一个嵌套块,但无论我把它放在哪里或尝试将它放在周围,一旦出现错误?它停止执行我的其余代码,这就是我的问题。我有一种感觉,我可能在我的第二个存储过程中没有正确地执行我的嵌套块...

下面是调用第一个存储过程的第二个存储过程的代码:

CREATE OR REPLACE PROCEDURE Get_Tables
/*
* Sept 26th, 2021
* To process each table in the schema, and output table-related lines.
*/
AS 
  CURSOR TablesSelected IS
    SELECT Table_Name
    FROM User_Tables
    ORDER BY Table_Name ASC;
  CurrentRow User_Tables%ROWTYPE;
  dt DATE := sysdate;
  wVersionNumber VARCHAR(4) := 'V3.0';
  wLeftPadTableName VARCHAR(100);
  wLengthOfStatement VARCHAR(100);

BEGIN
  DBMS_OUTPUT.PUT_LINE( '---- Oracle Catalog Extract Utility ' || wVersionNumber || ' ----' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- Run on '|| TO_CHAR(dt,'Mon DD,YYYY','NLS_DATE_LANGUAGE=English')||' at '||TO_CHAR(dt,'HH24:MI') );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- S T A R T I N G  T A B L E  D R O P S' );
  DBMS_OUTPUT.PUT_LINE( '----' );

  FOR CurrentRow IN TablesSelected LOOP
    DBMS_OUTPUT.PUT_LINE( 'DROP TABLE ' || CurrentRow.Table_Name);
  END LOOP;

  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- T A B L E  D R O P S  C O M P L E T E D' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- S T A R T I N G  T A B L E  C R E A T E' );
  DBMS_OUTPUT.PUT_LINE( '----' );

/* 
* Nested block starts
* LOOP gets all the tables in the database and aligns them up. 
*/
    DECLARE
      INVALID_COLUMN_EXCEPTION EXCEPTION;
      PRAGMA EXCEPTION_INIT(INVALID_COLUMN_EXCEPTION, -20100);
    BEGIN

  FOR CurrentRow IN TablesSelected LOOP
    wLengthOfStatement := LENGTH('CREATE TABLE' || CurrentRow.Table_Name || ' ' || '); -- ');
    wLeftPadTableName := LPAD('); -- ', wLengthOfStatement, ' ');
    DBMS_OUTPUT.PUT_LINE( '--   Start extracting table ' || CurrentRow.Table_Name);
    DBMS_OUTPUT.PUT_LINE('CREATE TABLE ' || CurrentRow.Table_Name || '( ');
    Extract_Columns(CurrentRow.Table_Name);
    DBMS_OUTPUT.PUT_LINE(wLeftPadTableName || 'END of table ' || CurrentRow.Table_Name || ' creation');
    DBMS_OUTPUT.PUT_LINE( '--' );
    DBMS_OUTPUT.PUT_LINE( '--' );
  END LOOP;

    EXCEPTION
      WHEN INVALID_COLUMN_EXCEPTION THEN
    DBMS_OUTPUT.PUT_LINE('================================================================================');   
        DBMS_OUTPUT.PUT_LINE('== EXCEPTION ' || SQLCODE || ' Raised - ' || SQLERRM);
        DBMS_OUTPUT.PUT_LINE('== Unable to complete table generation for ' || CurrentRow.Table_Name);
        DBMS_OUTPUT.PUT_LINE('================================================================================');
    END;

/* 
* Nested block ends 
*/

  DBMS_OUTPUT.PUT_LINE( '---- T A B L E  C R E A T E  C O M P L E T E D' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- Oracle Catalog Extract Utility ' || wVersionNumber || ' ----' );
  DBMS_OUTPUT.PUT_LINE( '---- Run Completed on '||TO_CHAR(dt,'Mon DD,YYYY','NLS_DATE_LANGUAGE=English')||' at '||TO_CHAR(dt,'HH24:MI') );

END;
/

当我打印出我的报告时...我引发的 ERROR 终止了循环的其余部分的执行,因此它不会获取其他 tables 及其行。

如果有 SQL 向导可以帮助我解决问题,我将不胜感激。我需要知道如何使我的 LOOP 和存储过程在引发异常后继续执行。

如果您希望 FOR 循环在异常发生后继续,请将嵌套块放在 FOR 循环中。
(您也不需要为自定义异常单独声明。)

CREATE OR REPLACE PROCEDURE Get_Tables
AS 
  CURSOR TablesSelected IS
    SELECT Table_Name
    FROM User_Tables
    ORDER BY Table_Name ASC;
  CurrentRow User_Tables%ROWTYPE;
  dt DATE := sysdate;
  wVersionNumber VARCHAR(4) := 'V3.0';
  wLeftPadTableName VARCHAR(100);
  wLengthOfStatement VARCHAR(100);
  INVALID_COLUMN_EXCEPTION EXCEPTION;
  PRAGMA EXCEPTION_INIT(INVALID_COLUMN_EXCEPTION, -20100);
BEGIN
  DBMS_OUTPUT.PUT_LINE( '---- Oracle Catalog Extract Utility ' || wVersionNumber || ' ----' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- Run on '|| TO_CHAR(dt,'Mon DD,YYYY','NLS_DATE_LANGUAGE=English')||' at '||TO_CHAR(dt,'HH24:MI') );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- S T A R T I N G  T A B L E  D R O P S' );
  DBMS_OUTPUT.PUT_LINE( '----' );

  FOR CurrentRow IN TablesSelected LOOP
    DBMS_OUTPUT.PUT_LINE( 'DROP TABLE ' || CurrentRow.Table_Name);
  END LOOP;

  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- T A B L E  D R O P S  C O M P L E T E D' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- S T A R T I N G  T A B L E  C R E A T E' );
  DBMS_OUTPUT.PUT_LINE( '----' );

  FOR CurrentRow IN TablesSelected LOOP
    wLengthOfStatement := LENGTH('CREATE TABLE' || CurrentRow.Table_Name || ' ' || '); -- ');
    wLeftPadTableName := LPAD('); -- ', wLengthOfStatement, ' ');
    DBMS_OUTPUT.PUT_LINE( '--   Start extracting table ' || CurrentRow.Table_Name);
    DBMS_OUTPUT.PUT_LINE('CREATE TABLE ' || CurrentRow.Table_Name || '( ');
  /* 
   * Nested block starts
   */
    BEGIN
      Extract_Columns(CurrentRow.Table_Name);
    EXCEPTION
      WHEN INVALID_COLUMN_EXCEPTION THEN
        DBMS_OUTPUT.PUT_LINE('================================================================================');
        DBMS_OUTPUT.PUT_LINE('== EXCEPTION ' || SQLCODE || ' Raised - ' || SQLERRM);
        DBMS_OUTPUT.PUT_LINE('== Unable to complete table generation for ' || CurrentRow.Table_Name);
        DBMS_OUTPUT.PUT_LINE('================================================================================');
    END;
  /*
   * Nested block ends 
   */
    DBMS_OUTPUT.PUT_LINE(wLeftPadTableName || 'END of table ' || CurrentRow.Table_Name || ' creation');
    DBMS_OUTPUT.PUT_LINE( '--' );
    DBMS_OUTPUT.PUT_LINE( '--' );
  END LOOP;

  DBMS_OUTPUT.PUT_LINE( '---- T A B L E  C R E A T E  C O M P L E T E D' );
  DBMS_OUTPUT.PUT_LINE( '----' );
  DBMS_OUTPUT.PUT_LINE( '---- Oracle Catalog Extract Utility ' || wVersionNumber || ' ----' );
  DBMS_OUTPUT.PUT_LINE( '---- Run Completed on '||TO_CHAR(dt,'Mon DD,YYYY','NLS_DATE_LANGUAGE=English')||' at '||TO_CHAR(dt,'HH24:MI') );
END;
/