对于除 ORA-00942 表不存在之外的所有错误,停止运行存储过程

Posted

技术标签:

【中文标题】对于除 ORA-00942 表不存在之外的所有错误,停止运行存储过程【英文标题】:Stop stored procedure from running for all errors except ORA-00942 table does not exist 【发布时间】:2015-03-06 15:50:45 【问题描述】:

我在 Oracle 11g 中有一个存储过程,它将删除某些表中特定客户端的记录。以下脚本是其设置的示例。即使引发异常,它也会继续运行每个块。如果出现除“-942 表不存在”之外的任何其他异常,我们希望它停止运行。如果表不存在,则程序的其余部分应继续运行,所有其他程序应使其停止。我该怎么做?

create or replace PROCEDURE SCHEMA.PURGE_RECORDS

(vCLIENT_ID IN VARCHAR2, pINPUTSCOPE IN VARCHAR2,
  pSUCCESS_IND OUT VARCHAR2, pOUTCOME_DESC OUT VARCHAR2)

AS

  VTABLE_NAME VARCHAR2(200);  
  vSQL VARCHAR2(10000);

BEGIN

  IF pINPUTSCOPE = 'ALL' THEN

    BEGIN
      VTABLE_NAME := 'TABLE NAME';
      vSQL := ' 
          DELETE FROM TABLENAME T WHERE EXISTS (SELECT 1 FROM TABLE2 TSK WHERE CLIENT = '''|| vCLIENT_ID ||''' AND ASK_ID = T.ASK_ID)   ';
      EXECUTE IMMEDIATE vSQL;   
      DBMS_OUTPUT.PUT_LINE (  VTABLE_NAME || '  Scope set: ' ||  pINPUTSCOPE || ' ' || '(' || TO_CHAR(SQL%ROWCOUNT) || ' ROWS DELETED)' || chr(10));
      EXCEPTION WHEN OTHERS THEN NULL; DBMS_OUTPUT.PUT_LINE('ERROR :  ' || VTABLE_NAME || ' ' ||  SQLERRM);
    END;

    BEGIN
      VTABLE_NAME := 'TABLE NAME';
      vSQL := ' 
          DELETE FROM TABLENAME3 T WHERE EXISTS (SELECT 1 FROM TABLE3 TSK WHERE CLIENT = '''|| vCLIENT_ID ||''' AND ASK_ID = T.ASK_ID)  ';
      EXECUTE IMMEDIATE vSQL;   
      DBMS_OUTPUT.PUT_LINE (  VTABLE_NAME || '  Scope set: ' ||  pINPUTSCOPE || ' ' || '(' || TO_CHAR(SQL%ROWCOUNT) || ' ROWS DELETED)' || chr(10));
      EXCEPTION WHEN OTHERS THEN NULL; DBMS_OUTPUT.PUT_LINE('ERROR :  ' || VTABLE_NAME || ' ' ||  SQLERRM);
    END;

    BEGIN
      VTABLE_NAME := 'TABLE NAME';
      vSQL := ' 
          DELETE FROM TABLENAME4 T WHERE EXISTS (SELECT 1 FROM TABLE4 TSK WHERE CLIENT = '''|| vCLIENT_ID ||''' AND ASK_ID = T.ASK_ID)  ';
      EXECUTE IMMEDIATE vSQL;   
      DBMS_OUTPUT.PUT_LINE (  VTABLE_NAME || '  Scope set: ' ||  pINPUTSCOPE || ' ' || '(' || TO_CHAR(SQL%ROWCOUNT) || ' ROWS DELETED)' || chr(10));
      EXCEPTION WHEN OTHERS THEN NULL; DBMS_OUTPUT.PUT_LINE('ERROR :  ' || VTABLE_NAME || ' ' ||  SQLERRM);
    END;

    BEGIN
      VTABLE_NAME := 'TABLE NAME';
      vSQL := ' 
          DELETE FROM TABLENAME5 T WHERE EXISTS (SELECT 1 FROM TABLE5 TSK WHERE CLIENT = '''|| vCLIENT_ID ||''' AND ASK_ID = T.ASK_ID)  ';
      EXECUTE IMMEDIATE vSQL;   
      DBMS_OUTPUT.PUT_LINE (  VTABLE_NAME || '  Scope set: ' ||  pINPUTSCOPE || ' ' || '(' || TO_CHAR(SQL%ROWCOUNT) || ' ROWS DELETED)' || chr(10));
      EXCEPTION WHEN OTHERS THEN NULL; DBMS_OUTPUT.PUT_LINE('ERROR :  ' || VTABLE_NAME || ' ' ||  SQLERRM);
    END;
  END IF;

END;

【问题讨论】:

你认为你可以更好地格式化这个问题吗?在当前状态下很难阅读。 当然。我希望这会更好。对此感到抱歉。 您应该使用至少 4 个空格来缩进所有代码。 感谢您对我的问题的更正。对此非常新……:/ 【参考方案1】:

您可以显式捕获 ORA-00942 错误,报告您想要的,然后忽略它;然后使用 RAISE 处理所有其他异常 - 这会将异常传播到下一个块,在这种情况下会导致过程终止 - 或者根本不捕获它们。

ORA-00942 不是the predefined exceptions 之一,因此您需要定义一个异常名称并使用the PRAGMA EXCEPTION_INIT clause 将异常关联到the internally defined exception number:

...
AS
  VTABLE_NAME VARCHAR2(200);  
  vSQL VARCHAR2(10000);

  NO_SUCH_TABLE EXCEPTION;
  PRAGMA EXCEPTION_INIT (NO_SUCH_TABLE, -942);
BEGIN

  IF pINPUTSCOPE = 'ALL' THEN

    BEGIN
      VTABLE_NAME := 'TABLE NAME';
      vSQL := ' 
          DELETE FROM TABLENAME T WHERE EXISTS (SELECT 1 FROM TABLE2 TSK WHERE CLIENT = '''|| vCLIENT_ID ||''' AND ASK_ID = T.ASK_ID)   ';
      EXECUTE IMMEDIATE vSQL;   
      DBMS_OUTPUT.PUT_LINE (  VTABLE_NAME || '  Scope set: ' ||  pINPUTSCOPE || ' ' || '(' || TO_CHAR(SQL%ROWCOUNT) || ' ROWS DELETED)' || chr(10));
      EXCEPTION
        WHEN NO_SUCH_TABLE THEN
          DBMS_OUTPUT.PUT_LINE('ERROR :  ' || VTABLE_NAME || ' ' ||  SQLERRM);
          -- this exception has been squashed
        WHEN OTHERS THEN
          DBMS_OUTPUT.PUT_LINE('ERROR :  ' || VTABLE_NAME || ' ' ||  SQLERRM);
          RAISE;
    END;
    ...

并在每个子块中重复异常捕获。 OTHERS 处理程序仍将捕获任何其他异常。捕获和挤压OTHERS 通常是一个坏主意,最好将其删除并让异常自然传播;即使您正在显示错误(假设运行此错误的人正在显示输出),您也会丢失原始问题的行号。所以你只需要做:

...
      EXECUTE IMMEDIATE vSQL;   
      DBMS_OUTPUT.PUT_LINE (  VTABLE_NAME || '  Scope set: ' ||  pINPUTSCOPE || ' ' || '(' || TO_CHAR(SQL%ROWCOUNT) || ' ROWS DELETED)' || chr(10));
      EXCEPTION
        WHEN NO_SUCH_TABLE THEN
          DBMS_OUTPUT.PUT_LINE('ERROR :  ' || VTABLE_NAME || ' ' ||  SQLERRM);
          -- this exception has been squashed, all others will propagate
    END;

    ...

【讨论】:

非常感谢亚历克斯!这正是我所需要的,并且有效!完美!

以上是关于对于除 ORA-00942 表不存在之外的所有错误,停止运行存储过程的主要内容,如果未能解决你的问题,请参考以下文章

SQL 错误:ORA-00942 表或视图不存在

java.sql.SQLSyntaxErrorException:ORA-00942:netbeans 8.0.1 中的表或视图不存在错误消息

ORA-00942:表或视图不存在 低级错误一例

异常 ORA-00942: 表或视图不存在 - 使用休眠会话插入现有表时

SQLDeveloper 触发器错误报告 - ORA-00942:表或视图不存在

SQLDeveloper触发器错误报告 - ORA-00942:表或视图不存在