※攔截例外
先看一個一定會死的例子
DECLARE i INTEGER; BEGIN i := 10/0; END;
※結果:
※根據框起來的訊息,去官網找,01476會對應 Error Code ,並把前面的0拿掉,了解後增加如下的程式碼:
DECLARE
i INTEGER;
BEGIN
i := 10/0;
DBMS_OUTPUT.PUT_LINE('這行印不到');
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('被除數不能是0');
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
被除數不能是0 SQLCODE=-1476 SQLERRM=ORA-01476: divisor is equal to zero
※ZERO_DIVEDE是針對這個程式使用的,如果不是這個例外,也就等於沒攔截到,那就是和沒寫是一樣的
DECLARE
i INTEGER;
BEGIN
i := 'S';
DBMS_OUTPUT.PUT_LINE('這行印不到');
EXCEPTION
WHEN VALUE_ERROR THEN
DBMS_OUTPUT.PUT_LINE('給值的型態或長度不正確');
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
給值的型態或長度不正確 SQLCODE=-6502 SQLERRM=ORA-06502: PL/SQL: numeric or value error: character to number conversion error
DECLARE
xxx_dname DEPT.DNAME%TYPE;
BEGIN
SELECT DNAME INTO xxx_dname
FROM DEPT
WHERE DEPTNO = 90;
DBMS_OUTPUT.PUT_LINE('這行印不到');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('找不到資料');
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
找不到資料 SQLCODE=100 SQLERRM=ORA-01403: no data found
※這個比較奇怪,錯誤的訊息不是100,是「no data found」,剛好裡面也有,所以我照打,還真的攔到了
DECLARE
xxx_dname DEPT.DNAME%TYPE;
BEGIN
SELECT DNAME INTO xxx_dname
FROM DEPT;
DBMS_OUTPUT.PUT_LINE('這行印不到');
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE('找到太多資料');
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
找到太多資料
SQLCODE=-1422
SQLERRM=ORA-01422: exact fetch returns more than requested number of rows
※以上的例子一個一個去查太累了,所以可以用others就一切掉定了,WHEN OTHERS THEN
※自定義例外
※沒有例外的訊息
DECLARE
i NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
SQLCODE=0
SQLERRM=ORA-0000: normal, successful completion
※宣告例外類型
DECLARE
i NUMBER := 6;
xxx_exp EXCEPTION;
BEGIN
IF i != 4 THEN
RAISE xxx_exp;
END IF;
EXCEPTION
WHEN xxx_exp THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
SQLCODE=1
SQLERRM=User-Defined Exception
※類型就是EXCEPTION,RAISE和java的throw類似
※自定例外代號
尤於上面的訊息太差了,有和沒有一樣,因為它的代號永遠都是1DECLARE
i NUMBER := 6;
xxx_exp EXCEPTION;
PRAGMA EXCEPTION_INIT(xxx_exp, -20111);
BEGIN
IF i != 4 THEN
RAISE xxx_exp;
END IF;
EXCEPTION
WHEN xxx_exp THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
SQLCODE=-20111
SQLERRM=ORA-20111:
※一定要叫PRAGMA,而自定的錯誤代碼是-20000 ~ -20999,看官網
※如果不是-20000 ~ -20999,例如-01476除零的例外,PRAGMA EXCEPTION_INIT(xxx_exp, -01476);,就會出如下的訊息:
SQLCODE=-1476
SQLERRM=ORA-01476: divisor is equal to zero
就好像變成除零例外的子類
※自定例外訊息
上面的程式碼,雖然解決了例外代號,但訊息仍然有和沒有一樣DECLARE
i NUMBER := 6;
xxx_exp EXCEPTION;
PRAGMA EXCEPTION_INIT(xxx_exp, -20111);
BEGIN
IF i != 4 THEN
RAISE_APPLICATION_ERROR(-20111, '自定義例外');
END IF;
EXCEPTION
WHEN xxx_exp THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※結果:
SQLCODE=-20111
SQLERRM=ORA-20111: 自定義例外
※例用RAISE_APPLICATION_ERROR就可以了,代號要和PRAGMA一樣
※簡化自定義例外訊息
DECLARE
i NUMBER := 6;
xxx_exp EXCEPTION;
BEGIN
IF i != 4 THEN
RAISE_APPLICATION_ERROR(-20111, '自定義例外');
END IF;
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('SQLCODE=' || SQLCODE);
DBMS_OUTPUT.PUT_LINE('SQLERRM=' || SQLERRM);
END;
※也就是省略了PRAGMA EXCEPTION_INIT(xxx_exp, -20111);,而EXCEPTION一定要用OTHERS就可以了,結果和上面的程式碼一樣

沒有留言:
張貼留言