※攔截例外
先看一個一定會死的例子
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就可以了,結果和上面的程式碼一樣
沒有留言:
張貼留言