异常处理语法与实例

2022-09-26 21:55:20 浏览数 (2)

0 总结

异常总结

  • 内部异常统一在《Database Error Messages》中,例如ORA-00910等等,其中-00910就是SQLCODE。
  • 内部异常有系统内部识别抛出,在Catch时只能使用Other关键字接受(… when others …)。
  • 预定义异常将一些常用SQLCODE绑定名称,所以在Catch是可以使用名字接收(… when ZERO_DIVIDE …)。
  • 用户自定异常有两种使用方式:
    • 定义·xxx EXCEPTION;变量,然后直接raise xxx;,sqlcode永远为1。
    • 触发指定sqlcode的异常:3.2 与 3.3中介绍。sqlcode为定义值,范围:-20000到-20999

sqlcode总结

  • 内部异常、预定义异常(=内部异常号绑定名字),sqlcode通常为负数,只有"no data found"是100。
  • 用户定义异常
    • 直接定义使用的sqlcode永远为1。
    • 用RAISE_APPLICATION_ERROR的范围:-20000到-20999

1 内部异常

  • 不能用名字catch,必须间接使用EXCEPTION_INIT定义名字来catch
  • 预定义异常相当于给内部异常一个名字

1.1 实例

代码语言:javascript复制
create table t12(info varchar(2));

BEGIN
  INSERT INTO t12 VALUES('11111111111');
EXCEPTION
  WHEN others THEN
    dbms_output.put_line(sqlcode);
    dbms_output.put_line(sqlerrm);
END;
/

-- -12899
-- ORA-12899: value too large for column "SYS"."T12"."INFO" (actual: 11, maximum: 2)

1.2 取值范围

从文档中看

sqlcode可以使用范围:-00001-99999,五位负数。

实例:

代码语言:javascript复制
...
ORA-12872: First slave parse gave different plan
ORA-12899: value too large for column string (actual: string, maximum: string)
ORA-12899: value too large for column string (actual: string, maximum: string)
ORA-12901: default temporary tablespace must be of TEMPORARY type
...

1.3 Raise与Catch方法

触发方式:

  • 系统系统触发,只能用others接收。
  • 用户自定义触发,可以用自定义标识符接受系统内部异常,注意SQLCODE必须为系统内部异常的CODE才能实现对应功能。
代码语言:javascript复制
create table t12(info varchar(2));

DECLARE
  vvv EXCEPTION;
  PRAGMA EXCEPTION_INIT(vvv, -12899);
BEGIN
  INSERT INTO t12 VALUES('11111111111');
EXCEPTION
  WHEN vvv THEN
    dbms_output.put_line(sqlcode);
    dbms_output.put_line(sqlerrm);
END;
/

2 预定义异常

  • 一共22个预定义异常
  • 注意所有预定义异常可以理解为Oracle内部异常加上STANDARD包中使用EXCEPTION_INIT定义了一些异常名,类似于1.3中的实例用法。
  • NO_DATA_FOUND 100是比较特殊的语法,唯一SQLCODE为正数的用法。

Exception Name

Error Code

内部异常

ACCESS_INTO_NULL

-6530

ORA-06530: Reference to uninitialized composite

CASE_NOT_FOUND

-6592

ORA-06592: CASE not found while executing CASE statement

COLLECTION_IS_NULL

-6531

ORA-06531: Reference to uninitialized collection

CURSOR_ALREADY_OPEN

-6511

ORA-06511: PL/SQL: cursor already open

DUP_VAL_ON_INDEX

-1

ORA-00001: unique constraint (*string*.*string*) violated

INVALID_CURSOR

-1001

INVALID_NUMBER

-1722

ORA-01722: invalid number

LOGIN_DENIED

-1017

NO_DATA_FOUND

100

特殊

NO_DATA_NEEDED

-6548

ORA-06548: no more rows needed

NOT_LOGGED_ON

-1012

PROGRAM_ERROR

-6501

ROWTYPE_MISMATCH

-6504

SELF_IS_NULL

-30625

STORAGE_ERROR

-6500

ORA-06500: PL/SQL: storage error

SUBSCRIPT_BEYOND_COUNT

-6533

SUBSCRIPT_OUTSIDE_LIMIT

-6532

SYS_INVALID_ROWID

-1410

TIMEOUT_ON_RESOURCE

-51

TOO_MANY_ROWS

-1422

ORA-01422: exact fetch returns more than requested number of rows

VALUE_ERROR

-6502

ORA-06502: PL/SQL: numeric or value error*string*

ZERO_DIVIDE

-1476

内部异常与预定义异常等价实例

内部异常

代码语言:javascript复制
DECLARE
  stock_price   NUMBER := 9.73;
  net_earnings  NUMBER := 0;
  pe_ratio      NUMBER;
BEGIN
  pe_ratio := stock_price / net_earnings;  -- raises ZERO_DIVIDE exception
  DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);
EXCEPTION
  WHEN others THEN
    dbms_output.put_line(sqlcode);
    dbms_output.put_line(sqlerrm);
END;
/

-- -1476
-- ORA-01476: divisor is equal to zero

预定义异常

代码语言:javascript复制
DECLARE
  stock_price   NUMBER := 9.73;
  net_earnings  NUMBER := 0;
  pe_ratio      NUMBER;
BEGIN
  pe_ratio := stock_price / net_earnings;  -- raises ZERO_DIVIDE exception
  DBMS_OUTPUT.PUT_LINE('Price/earnings ratio = ' || pe_ratio);
EXCEPTION
  WHEN ZERO_DIVIDE THEN
    dbms_output.put_line(sqlcode);
    dbms_output.put_line(sqlerrm);
END;
/

-- -1476
-- ORA-01476: divisor is equal to zero

3 用户定义异常

3.1 用户自定义异常:sqlcode=1

代码语言:javascript复制
DECLARE
  xxx  EXCEPTION;
BEGIN
  raise xxx;
EXCEPTION
  WHEN xxx THEN
    dbms_output.put_line(sqlcode);
    dbms_output.put_line(sqlerrm);
END;
/

-- 1
-- User-Defined Exception

3.2 others接收实例:sqlcode=-20222

sqlcode范围:-20000到-20999

代码语言:javascript复制
BEGIN
  RAISE_APPLICATION_ERROR(-20222, 'raise my zero devide!');
EXCEPTION
  WHEN others THEN
    dbms_output.put_line(sqlcode);
    dbms_output.put_line(sqlerrm);
END;
/

-- -20222
-- ORA-20222: raise my zero devide!

3.3 名字接收实例:sqlcode=-20222

sqlcode范围:-20000到-20999

代码语言:javascript复制
DECLARE
  zzz EXCEPTION;
  PRAGMA EXCEPTION_INIT (zzz, -20222);
BEGIN
  RAISE_APPLICATION_ERROR(-20222, 'raise my zero devide!');
EXCEPTION
  WHEN zzz THEN
    dbms_output.put_line(sqlcode);
    dbms_output.put_line(sqlerrm);
END;
/

-- -20222
-- ORA-20222: raise my zero devide!

0 人点赞