PL/SQL 异常

-- Start

PL/SQL 异常处理和 Java 有点类似,我们可以捕获并处理异常,抛出异常,自定义异常等。下面是一个简单的例子。

DECLARE
NAME  VARCHAR2(10);

BEGIN
  SELECT 'SHANGBO' INTO NAME FROM DUAL WHERE 1 = 2;
  
  -- 异常处理部分
  EXCEPTION
	-- 异常处理分支一:处理 NO_DATA_FOUND 异常
    WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE ('NO DATA FOUND');
	-- 异常处理分支二:OTHERS 表示处理任何类型的异常
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE ('UNEXPECTED ERROR');
      RAISE; -- RAISE 表示向上抛出异常
END;

Oracle 预定义异常

上面的例子中,NO_DATA_FOUND 是 Oracle 预定义异常,由 Oracle 自动抛出,让我们来看看 Oracle 都提供了哪些预定义异常,如下所示,我们可以根据名字很容易知道它们的意思。

Exception Name         Error Code
ACCESS_INTO_NULL           -6530
CASE_NOT_FOUND             -6592
COLLECTION_IS_NULL         -6531
CURSOR_ALREADY_OPEN        -6511
DUP_VAL_ON_INDEX           -1
INVALID_CURSOR             -1001
INVALID_NUMBER             -1722
LOGIN_DENIED               -1017
NO_DATA_FOUND              +100
NO_DATA_NEEDED             -6548
NOT_LOGGED_ON              -1012
PROGRAM_ERROR              -6501
ROWTYPE_MISMATCH           -6504
SELF_IS_NULL               -30625
STORAGE_ERROR              -6500
SUBSCRIPT_BEYOND_COUNT     -6533
SUBSCRIPT_OUTSIDE_LIMIT    -6532
SYS_INVALID_ROWID          -1410
TIMEOUT_ON_RESOURCE        -51
TOO_MANY_ROWS              -1422
VALUE_ERROR                -6502
ZERO_DIVIDE                -1476

Oracle 内部定义异常

Oracle 内部定义异常没有名字,只有错误代码(Error Code),如死锁(ORA-00060),它也是由 Oracle 自动抛出的,我们可以在 OTHERS 分支中捕获并处理它,通常我们不推荐这种做法。除此之外,我们还可以给内部定义异常起个名字,这样我们就可以单独处理它了,如下。

DECLARE
NAME  VARCHAR2(10);

-- 定义异常
DEADLOCK_EXCEPTION EXCEPTION;
-- 关联异常和错误代码
PRAGMA EXCEPTION_INIT(DEADLOCK_EXCEPTION, -60);

BEGIN
  SELECT 'SHANGBO' INTO NAME FROM DUAL WHERE 1 = 2;
  
  -- 异常处理部分
  EXCEPTION
	-- 异常处理分支一:处理 NO_DATA_FOUND 异常
    WHEN NO_DATA_FOUND THEN
      DBMS_OUTPUT.PUT_LINE ('NO DATA FOUND');
	-- 异常处理分支二:处理 DEADLOCK_EXCEPTION 异常
    WHEN DEADLOCK_EXCEPTION THEN
      DBMS_OUTPUT.PUT_LINE ('DEAD LOCK, TRY AGAIN LATER');
	-- 异常处理分支三:OTHERS 表示处理任何类型的异常
    WHEN OTHERS THEN
      DBMS_OUTPUT.PUT_LINE ('UNEXPECTED ERROR');
      RAISE; -- RAISE 表示向上抛出异常
END;

自定义异常

我们还可以自定义异常,自定义异常需要我们自己抛出,下面是一个简单的例子。

DECLARE
NAME  VARCHAR2(10);

-- 自定义异常
NULL_POINT_EXCEPTION EXCEPTION;

BEGIN
  IF NAME IS NULL THEN
    RAISE NULL_POINT_EXCEPTION; -- 抛出异常给调用者
  END IF;
END;

上面的例子中,我们的自定义异常没有错误代码,事实上,我们还可以给它赋一个错误代码,这个错误代码必须是整数且范围是(-20000..-20999), 如下。

DECLARE
NAME  VARCHAR2(10);

-- 自定义异常
NULL_POINT_EXCEPTION EXCEPTION;
-- 给自定义异常赋错误代码
PRAGMA EXCEPTION_INIT (NULL_POINT_EXCEPTION, -20000);

BEGIN
  IF NAME IS NULL THEN
    RAISE NULL_POINT_EXCEPTION; -- 抛出异常给调用者
  END IF;
END;

上面的例子是比较繁琐的,有没有办法让我们可以不定义异常,在需要的时候我们又可以抛出异常呢?呵呵,答案是有,下面的例子和上面完全相同。

DECLARE
NAME  VARCHAR2(10);

BEGIN
  IF NAME IS NULL THEN
    RAISE_APPLICATION_ERROR(-20000, 'name cannot null'); -- 抛出异常给调用者
  END IF;
END;


异常与事务

当 PL/SQL 抛出异常时,它并不会自动回滚事务,我们需要手动回滚,下面是一个简单的例子。

BEGIN

UPDATE EMPLOYEES SET SALARY = 9999 WHERE EMPLOYEE_ID = -1;

EXCEPTION
  WHEN OTHERS THEN
    DBMS_OUTPUT.PUT_LINE('Error Code:' || SQLCODE || ', Error Message: ' || SQLERRM);
    ROLLBACK;
    RAISE;
END;

--更多参见:Oracle PL/SQL 精萃

-- 声明:转载请注明出处

-- Last Edited on 2015-04-17

-- Created by ShangBo on 2015-04-16

-- End

你可能感兴趣的:(oracle,sql,plsql)