Oracle Exception

Oracle异常的文档在这里:https://docs.oracle.com/cd/B10501_01/appdev.920/a96624/07_errs.htm

总的来讲,Oracle Exception分为如下3类:

  • 预定义异常
  • 非预定义异常-
  • 自定义异常

处理方法也分为3类:
处理方法分为:直接抛出异常、内部块处理异常、游标处理异常

  • 预定义异常:由PL/SQL定义的异常。由于它们已在standard包中预定义了,因此,这些预定义异常可以直接在程序中使用,而不必再定义部分声明。
  • 非预定义异常:用于处理预定义异常所不能处理的Oracle错误。
  • 自定义异常:用户自定义的异常,需要在定义部分声明后才能在可执行部分使用。用户自定义异常对应的错误不一定是Oracle错误,例如它可能是一个数据错误。

三种异常中,预定义与非预定义异常都与Oracle错误有关,并且由Oracle隐含自动抛出,而自定义异常与Oracle错误没有任何关联,由开发人员为特定情况所定义的异常,需要显式抛出(raise)。

1.预定义异常

1.1 预定义异常种类

Exception Oracle Error SQLCODE Value
ACCESS_INTO_NULL ORA-06530 -6530
CASE_NOT_FOUND ORA-06592 -6592
COLLECTION_IS_NULL ORA-06531 -6531
CURSOR_ALREADY_OPEN ORA-06511 -6511
DUP_VAL_ON_INDEX ORA-00001 -1
INVALID_CURSOR ORA-01001 -1001
INVALID_NUMBER ORA-01722 -1722
LOGIN_DENIED ORA-01017 -1017
NO_DATA_FOUND ORA-01403 +100
NOT_LOGGED_ON ORA-01012 -1012
PROGRAM_ERROR ORA-06501 -6501
ROWTYPE_MISMATCH ORA-06504 -6504
SELF_IS_NULL ORA-30625 -30625
STORAGE_ERROR ORA-06500 -6500
SUBSCRIPT_BEYOND_COUNT ORA-06533 -6533
SUBSCRIPT_OUTSIDE_LIMIT ORA-06532 -6532
SYS_INVALID_ROWID ORA-01410 -1410
TIMEOUT_ON_RESOURCE ORA-00051 -51
TOO_MANY_ROWS ORA-01422 -1422
VALUE_ERROR ORA-06502 -6502
ZERO_DIVIDE ORA-01476 -1476
说明一下:“| :--: | :--: | :--: |”中的--左边:表示左对齐,右边:表示右对齐,两边都有表示居中对齐。

1.2 预定义异常发生场景

ID Exception Raised when ...
1 ACCESS_INTO_NULL Your program attempts to assign values to the attributes of an uninitialized (atomically null) object.
2 CASE_NOT_FOUND None of the choices in the WHEN clauses of a CASE statement is selected, and there is no ELSE clause.
3 COLLECTION_IS_NULL Your program attempts to apply collection methods other than EXISTS to an uninitialized (atomically null) nested table or varray, or the program attempts to assign values to the elements of an uninitialized nested table or varray.
4 CURSOR_ALREADY_OPEN Your program attempts to open an already open cursor. A cursor must be closed before it can be reopened. A cursor FOR loop automatically opens the cursor to which it refers. So, your program cannot open that cursor inside the loop.
5 DUP_VAL_ON_INDEX Your program attempts to store duplicate values in a database column that is constrained by a unique index.
6 INVALID_CURSOR Your program attempts an illegal cursor operation such as closing an unopened cursor.
7 INVALID_NUMBER In a SQL statement, the conversion of a character string into a number fails because the string does not represent a valid number. (In procedural statements, VALUE_ERROR is raised.) This exception is also raised when the LIMIT-clause expression in a bulk FETCH statement does not evaluate to a positive number.
8 LOGIN_DENIED Your program attempts to log on to Oracle with an invalid username and/or password.
9 NO_DATA_FOUND A SELECT INTO statement returns no rows, or your program references a deleted element in a nested table or an uninitialized element in an index-by table. SQL aggregate functions such as AVG and SUM always return a value or a null. So, a SELECT INTO statement that calls an aggregate function never raises NO_DATA_FOUND. The FETCH statement is expected to return no rows eventually, so when that happens, no exception is raised.
10 NOT_LOGGED_ON Your program issues a database call without being connected to Oracle.
11 PROGRAM_ERROR PL/SQL has an internal problem.
12 ROWTYPE_MISMATCH The host cursor variable and PL/SQL cursor variable involved in an assignment have incompatible return types. For example, when an open host cursor variable is passed to a stored subprogram, the return types of the actual and formal parameters must be compatible.
13 SELF_IS_NULL Your program attempts to call a MEMBER method on a null instance. That is, the built-in parameter SELF (which is always the first parameter passed to a MEMBER method) is null.
14 STORAGE_ERROR PL/SQL runs out of memory or memory has been corrupted.
15 SUBSCRIPT_BEYOND_COUNT Your program references a nested table or varray element using an index number larger than the number of elements in the collection.
16 SUBSCRIPT_OUTSIDE_LIMIT Your program references a nested table or varray element using an index number (-1 for example) that is outside the legal range.
17 SYS_INVALID_ROWID The conversion of a character string into a universal rowid fails because the character string does not represent a valid rowid.
18 TIMEOUT_ON_RESOURCE A time-out occurs while Oracle is waiting for a resource.
19 TOO_MANY_ROWS A SELECT INTO statement returns more than one row.
20 VALUE_ERROR An arithmetic, conversion, truncation, or size-constraint error occurs. For example, when your program selects a column value into a character variable, if the value is longer than the declared length of the variable, PL/SQL aborts the assignment and raises VALUE_ERROR. In procedural statements, VALUE_ERROR is raised if the conversion of a character string into a number fails. (In SQL statements, INVALID_NUMBER is raised.)
21 ZERO_DIVIDE Your program attempts to divide a number by zero.

中文解释参考:https://blog.csdn.net/bbliutao/article/details/7833721

2.非预定义异常

非预定义异常用于处理与上述21个预定义异常无关的Oracle错误,如果要处理没有与预定义异常对应的Oracle错误时,则需要为这些Oracle错误声明相应的非预定义异常。
声明这样的异常需要使用exception_init编译指令。exception_init编译指令的定义如下:

pragma exception_init(exception_name,Oracle_error_number);
说明:exception_name是预先被声明的异常名,Oracle_error_number是错误号,这条命令必须写在定义部分。

例子

declare
    e_inte exception; --定义
    pragma exception_intt(e_inte,-2291); --关联Oracle错误ORA-2291
begin
    update emp set deptno=&dno where empno=&eno;
exception
    when e_inte then
    dbms_output.put_line('部门不存在');
end;

官方例子

DECLARE
   deadlock_detected EXCEPTION;
   PRAGMA EXCEPTION_INIT(deadlock_detected, -60);
BEGIN
   ... -- Some operation that causes an ORA-00060 error
EXCEPTION
   WHEN deadlock_detected THEN
      -- handle the error
END;

3.自定义异常

3.1 语法定义

自定义异常与Oracle错误没有任何关联,由开发人员为特定情况所定义的异常,需要显式抛出(raise)。其具有特点是:

  • 自定义异常的声明与变量的声明类似,但异常是一个错误状态,而不是一个数据项。
  • 因为不是数据项,所以异常不能出现在赋值语句和sql语句中,但异常的作用域与定义部分其它变量的作用域相同。
  • 如果一个自定义异常被传递到作用域外,则不能再通过原来的名字引用它。如果确有需要,可以在包中声明异常,这个异常就可以在任何块中使用,使用时在异常前加包名前缀即可。
CREATE PROCEDURE raise_salary (emp_id NUMBER, amount NUMBER) AS
   curr_sal NUMBER;
BEGIN
   SELECT sal INTO curr_sal FROM emp WHERE empno = emp_id;
   IF curr_sal IS NULL THEN
      /* Issue user-defined error message. */
      raise_application_error(-20101, 'Salary is missing');
   ELSE
      UPDATE emp SET sal = curr_sal + amount WHERE empno = emp_id;
   END IF;
END raise_salary;
当curr_sal 为空时会抛出异常信息。

当一个异常产生时,控制权立即转交给块的异常处理部分。如果该块没有异常处理部分,则向该块的外一层块传递。一旦控制权交给了异常处理部分,则再没有办法回到块可执行部分

3.2 raise抛出异常的三种方法

    1. Raise exception:用于抛出当前程序中定义的异常或在 standard 中的系统异常。
    1. Raise package.exception:用于抛出有一些异常是定义在非标准包中的,如UTL_FILE,DBMS_SQL以及程序员创建的包中异常
    1. Raise:不带任何参数,这种情况只出现在希望将当前的异常传到外部程序时。

3.3 生产使用

  • 抛出异常语句块,判定何种情况抛出何种异常
/*如果当前账期日没有0082山东支付对账,日结算不进行,并告警*/
IF SDP_ACC_FLOW_COUNT = 0 THEN
  RAISE EXC_SDP_NO_ACC;
ELSE
/*查询最近一条0082山东支付对账流程的状态*/
SELECT FLOW.STATE
  INTO SDP_ACC_STATE
  FROM (SELECT T.STATE,
               ROW_NUMBER() OVER(PARTITION BY T.SETTLEDATE ORDER BY T.CREATETIME DESC) ROWNUMBER
          FROM AF_FLOW T
         WHERE T.PROCESSID = P_PROCESS_ID_SDP AND T.SETTLEDATE = P_DATE) FLOW
 WHERE ROWNUMBER = 1;
  /*最近一条0082山东支付对账流程状态不是Finish,日结算不进行,并告警*/
  IF SDP_ACC_STATE <> 'Finish' THEN
    RAISE EXC_SDP_UNFINISHED_ACC;
  END IF;
END IF;
  • 异常处理块(插入告警表告警记录)
/*处理异常*/
EXCEPTION
/*当前账期日没有进行全网支付对账*/
  WHEN EXC_FNP_NO_ACC THEN
    LOG_ALARM_HELPER('[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 没有进行全网支付对账',0,'cmup-settle-pro','FNP','');
    ALARM_MESSAGE := '[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 没有进行全网支付对账';
/*当前账期日的全网支付对账未全部完成*/
  WHEN EXC_FNP_UNFINISHED_ACC THEN
    LOG_ALARM_HELPER('[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 有部分业务线未完成全网支付流程,业务线为:' || FNP_UNFINISHED_ACC,0,'cmup-settle-pro','FNP','');
    ALARM_MESSAGE := '[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 有部分业务线未完成全网支付流程,业务线为:' || FNP_UNFINISHED_ACC;
/*当前账期日没有进行0082山东支付对账*/
  WHEN EXC_SDP_NO_ACC THEN
    LOG_ALARM_HELPER('[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 没有进行0082山东支付对账',0,'cmup-settle-pro','FNP','');
    ALARM_MESSAGE := '[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 没有进行0082山东支付对账';
/*当前账期日的0082山东支付对账未全部完成*/
  WHEN EXC_SDP_UNFINISHED_ACC THEN
    LOG_ALARM_HELPER('[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 未完成0082山东支付对账流程',0,'cmup-settle-pro','FNP','');
    ALARM_MESSAGE := '[失败]全网支付日结算流程无法开始,当前账期日:' || P_DATE || ' 未完成0082山东支付对账流程';
/*系统运行异常*/
  WHEN OTHERS THEN
    LOG_ALARM_HELPER('[失败]系统异常,全网支付日结算程序出错,请查看相关运行日志!',1,'cmup-settle-pro','FNP','');
    /*将系统异常具体信息抛给后台程序打印出来*/
    RAISE;

不同处理规则如图所示:


pls81009_propagation_rules_example1.gif
pls81010_propagation_rules_example2.gif

pls81011_propagation_rules_example3.gif
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 1.PLSQL入门 Oracle数据库对SQL进行了扩展,然后加入了一些编程语言的特点,可以对SQL的执行过程进行...
    随手点灯阅读 596评论 0 8
  • 1.1 基本结构 PL/SQL程序由三个块组成,即声明部分、执行部分、异常处理部分。 1.2 命名规则 1.3 记...
    慢清尘阅读 3,844评论 3 14
  • 麻麻小米想逛街淘点货,姐姐红豆、弟弟松子随同。天气的反常,阳光指数直逼夏日,东南方的11月中下旬仍穿着短袖破洞裤出...
    小米粥里的一条虫阅读 331评论 0 1
  • 几个月前,某个好友和我说,好羡慕那些可以出国的人,我问:“也没有很多人出国读书吧,毕竟费用不小”。她说:“她们有些...
    骆小颖阅读 234评论 0 0