美文网首页
九、存储过程中异常的处理

九、存储过程中异常的处理

作者: lifeline张 | 来源:发表于2019-04-18 17:10 被阅读0次

原则如下:
1、存储过程中的异常要在本存储过程中进行处理。
2、存储过程中调用存储过程,被调用的如果发生了异常,一般父存储过程需要终止。
3、子存储过程中的异常处理不得污染父存储过程中的异常处理。

在这样的原则下,每个存储过程都要进行异常的声明与处理,处理完毕之后要抛出异常对父存储过程进行中断,否则因为子存储过程中的异常已经得到了处理,父存储过程会继续执行下去。又因为不能使父存储过程的异常处理被污染,所以最好的处理异常的方式就是声明变量,该变量专门为异常而存在,发生异常则变量值改变,处理完异常后,在父存储过程中判断该变量的值,如果子存储过程中发生了异常,则主动抛出异常,中断父存储过程的运行,这样就能分清楚异常到底是发生在具体的哪个存储过程中了。所以以后的异常处理就采用强哥的那种方式了。
如上。
测试存储过程:

CREATE OR REPLACE PACKAGE TEST_ROBACK IS

  PROCEDURE PROMAIN(O_FLAG OUT VARCHAR2, O_RESULT OUT VARCHAR2);

  PROCEDURE PROCH1(O_FLAG OUT VARCHAR2, O_RESULT OUT VARCHAR2);

END TEST_ROBACK;
CREATE OR REPLACE PACKAGE BODY TEST_ROBACK IS

  PROCEDURE PROMAIN(O_FLAG OUT VARCHAR2, O_RESULT OUT VARCHAR2) IS
    V_FLAG   VARCHAR2(1) := '0';
    V_RESULT VARCHAR2(1000) := '';
    E_EXCEPTION EXCEPTION;
  BEGIN
    O_FLAG   := '0';
    O_RESULT := '处理成功';
    PROCH1(O_FLAG => V_FLAG, O_RESULT => V_RESULT);
    IF (V_FLAG != '0') THEN
      RAISE E_EXCEPTION;
    END IF;
    COMMIT;
  EXCEPTION
    WHEN E_EXCEPTION THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
      DBMS_OUTPUT.PUT_LINE('子过程发生异常');
      ROLLBACK;
    WHEN OTHERS THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
      DBMS_OUTPUT.PUT_LINE('主过程发生异常');
      ROLLBACK;
  END PROMAIN;

  PROCEDURE PROCH1(O_FLAG OUT VARCHAR2, O_RESULT OUT VARCHAR2) IS
    V_SQL VARCHAR2(1000) := '';
  
    --用来接收本存储过程中调用的其他的存储过程的返回结果
    V_FLAG   VARCHAR2(1) := '0';
    V_RESULT VARCHAR2(1000) := '';
    E_EXCEPTION EXCEPTION;
    --用来返回本存储过程的执行结果
  BEGIN
    O_FLAG   := '0';
    O_RESULT := '执行成功';
    V_SQL    := 'INSERT INTO AZWZ(CLAIMINFO) VALUES (''1'')';
    EXECUTE IMMEDIATE V_SQL;
    RAISE E_EXCEPTION;
  EXCEPTION
    WHEN E_EXCEPTION THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
    WHEN OTHERS THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
  END PROCH1;

BEGIN
  DBMS_OUTPUT.PUT_LINE('TEST');
END TEST_ROBACK;

关于raise_application_error的用法:

CREATE OR REPLACE PACKAGE BODY TEST_ROBACK IS

  PROCEDURE PROMAIN(O_FLAG OUT VARCHAR2, O_RESULT OUT VARCHAR2) IS
    E_EXCEPTION EXCEPTION;
    PRAGMA EXCEPTION_INIT(E_EXCEPTION, -20999);
  BEGIN
    O_FLAG   := '0';
    O_RESULT := '处理成功';
    PROCH1;
    COMMIT;
  EXCEPTION
    WHEN E_EXCEPTION THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
      DBMS_OUTPUT.PUT_LINE(SQLERRM);
      ROLLBACK;
    WHEN OTHERS THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
      DBMS_OUTPUT.PUT_LINE('主过程发生异常');
      ROLLBACK;
  END PROMAIN;

  PROCEDURE PROCH1 IS
    V_SQL VARCHAR2(1000) := '';
  BEGIN
    V_SQL := 'INSERT INTO AZWZ(CLAIMINFO,A) VALUES (''1'')';
    EXECUTE IMMEDIATE V_SQL;
  EXCEPTION
    WHEN OTHERS THEN
      RAISE_APPLICATION_ERROR(-20999, SQLERRM);
  END PROCH1;

BEGIN
  DBMS_OUTPUT.PUT_LINE('TEST');
END TEST_ROBACK;

综上,异常处理大概有两种方式:

  • 在子过程中进行异常处理,同时用改变返回值的方式在主过程中进行子过程是否发生异常的判断
    -在主过程中定义异常号, 在子过程中进行异常处理,同时采用raise_application_error的方式抛出自定义异常号及异常信息,然后在主过程中直接捕获。这种方式的sqlcode只能在-20000到-20999

使用专门的表保存错误

将异常保存到专门的表格中:

-- Create table
create table A_LOG
(
  id             VARCHAR2(100) not null,
  proce_name     VARCHAR2(30),
  log_level      VARCHAR2(2),
  log_info       VARCHAR2(1000),
  makedate       DATE,
  maketime       VARCHAR2(10),
  standbystring1 VARCHAR2(100),
  standbystring2 VARCHAR2(100)
)
-- Create sequence 
create sequence MY_SEQ
minvalue 1
maxvalue 9999999999999999999999999999
start with 81
increment by 1
cache 20;

日志类存储过程:

create or replace package Z_LOG is

  INTO_LEVEL CONSTANT A_LOG.LOG_LEVEL%TYPE := '1';
  ERR_LEVEL  CONSTANT A_LOG.LOG_LEVEL%TYPE := '2';

  PROCEDURE LOG(I_PROCEDURENAME A_LOG.PROCE_NAME%TYPE,
                I_LOGLEVEL      A_LOG.LOG_LEVEL%TYPE,
                I_LOGINFO       A_LOG.LOG_INFO%TYPE);

end Z_LOG;
create or replace package body Z_LOG is

  PROCEDURE LOG(I_PROCEDURENAME A_LOG.PROCE_NAME%TYPE,
                I_LOGLEVEL      A_LOG.LOG_LEVEL%TYPE,
                I_LOGINFO       A_LOG.LOG_INFO%TYPE) IS
    PRAGMA AUTONOMOUS_TRANSACTION;
    V_SQL VARCHAR(1000);
    LOG_EXCEPTION EXCEPTION;
  BEGIN
    V_SQL := 'insert into A_LOG
  (ID, PROCE_NAME, LOG_LEVEL, LOG_INFO, MAKEDATE, MAKETIME)
VALUES
  (MY_SEQ.NEXTVAL,' || ':1,' || ':2,' || ':3,' ||
             'TRUNC(SYSDATE),TO_CHAR(SYSDATE,  ''HH24:MM:SS''))';
    EXECUTE IMMEDIATE V_SQL
      USING I_PROCEDURENAME, I_LOGLEVEL, I_LOGINFO;
    COMMIT;
  
  EXCEPTION
    WHEN OTHERS THEN
      RAISE LOG_EXCEPTION;
  END LOG;

end Z_LOG;

测试类:

CREATE OR REPLACE PACKAGE TEST_ROBACK IS

  PROCEDURE PROMAIN(O_FLAG OUT VARCHAR2, O_RESULT OUT VARCHAR2);

  PROCEDURE PROCH1;

END TEST_ROBACK;
CREATE OR REPLACE PACKAGE BODY TEST_ROBACK IS

  PROCEDURE PROMAIN(O_FLAG OUT VARCHAR2, O_RESULT OUT VARCHAR2) IS
    E_EXCEPTION EXCEPTION;
    PRAGMA EXCEPTION_INIT(E_EXCEPTION, -20009);
    V_PRO_NAME A_LOG.PROCE_NAME%TYPE := 'PROMAIN';
  BEGIN
    Z_LOG.LOG(V_PRO_NAME, '1', '开始调用主过程');
    O_FLAG   := '0';
    O_RESULT := '处理成功';
    PROCH1;
  EXCEPTION
    WHEN E_EXCEPTION THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
      Z_LOG.LOG(V_PRO_NAME, '2', SQLERRM);
      ROLLBACK;
    WHEN OTHERS THEN
      O_FLAG   := '1';
      O_RESULT := '处理失败';
      Z_LOG.LOG(V_PRO_NAME, '2', SQLERRM);
      ROLLBACK;
  END PROMAIN;

  PROCEDURE PROCH1 IS
    V_SQL      VARCHAR2(1000) := '';
    V_PRO_NAME A_LOG.PROCE_NAME%TYPE := 'PROCH1';
    V_PARAM    VARCHAR2(2) := '1';
  BEGIN
    Z_LOG.LOG(V_PRO_NAME, '1', '开始调用子过程');
    insert into AZWZ (CLAIMINFO) VALUES ('2');
    V_SQL := 'INSERT INTO AZWZ(CLAIMINFO,A) VALUES (''' || V_PARAM || ''')';
    EXECUTE IMMEDIATE V_SQL;
  EXCEPTION
    WHEN OTHERS THEN
      Z_LOG.LOG(V_PRO_NAME, '2', V_SQL);
      ROLLBACK;
      RAISE_APPLICATION_ERROR(-20009, V_SQL);
  END PROCH1;

BEGIN
  DBMS_OUTPUT.PUT_LINE('TEST');
END TEST_ROBACK;

事务控制

在上面的示例中要注意事务控制,在日志类中采用自治事务。这样的话,每次commit就只提交本过程中的dml,而不会影响到调用本过程的其他过程的事务。

相关文章

  • 九、存储过程中异常的处理

    原则如下:1、存储过程中的异常要在本存储过程中进行处理。2、存储过程中调用存储过程,被调用的如果发生了异常,一般父...

  • 第17课 存储过程中的"异常处理"

    异常处理 如果出现报错了, 怎么办 搁在以前, 直接就停了 有了异常处理, 我们可以选择继续还是终止 这段代码会报...

  • 异常处理设计文档

    一、异常处理流程说明 在ESB处理过程中,若发生异常,将进入异常流程的处理。一个异常处理流程大致如下: ESB处理...

  • 【九】异常处理

    1.异常产生&异常处理 异常概述 什么是异常?Java代码在运行时期发生的问题就是异常。在Java中,把异常信息封...

  • 异常处理器

    springmvc在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻...

  • SpringMVC异常处理器

    SpringMVC在处理请求过程中出现异常信息交由异常处理器进行处理,自定义异常处理器可以实现一个系统的异常处理逻...

  • SpringBoot-统一异常处理

    SpringBoot-统一异常处理 一、什么是异常处理 异常(exception) 是程序运行过程中发生的事件, ...

  • MySQL 存储过程中的异常

    1. 定义异常捕获类型及处理方法: 这里面需要注意几点:a 、condition_value [,conditio...

  • SqlServer存储过程异常处理

    微软平台的软件开发系统中,有着一套自己的约定规则。熟悉.net开发的都会对异常处理不陌生,现阶段的各种编程语言中,...

  • 异常

    异常机制 处理程序运行过程中的异常 异常类 java中有许多异常类,例如NullPointException,Ar...

网友评论

      本文标题:九、存储过程中异常的处理

      本文链接:https://www.haomeiwen.com/subject/tzbtgqtx.html