对于除 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 表不存在之外的所有错误,停止运行存储过程的主要内容,如果未能解决你的问题,请参考以下文章
java.sql.SQLSyntaxErrorException:ORA-00942:netbeans 8.0.1 中的表或视图不存在错误消息
异常 ORA-00942: 表或视图不存在 - 使用休眠会话插入现有表时