set serveroutput on <<DEMO_AND_TEST_EXCEPTIONS>> DECLARE MYOWNNODATAFOUND EXCEPTION; --ERROR CAUSED BY PRAGMA EXCEPTION_INIT (MYOWNNODATAFOUND, -1403); -- Cannot rename Oracle native exceptions if their numbers are already named -- in DBMS_STANDARD, e.g., ORA-01403 no data found userrange_exc_no constant number := -20202; USERRANGE_EXCEPTION EXCEPTION; PRAGMA EXCEPTION_INIT (USERRANGE_EXCEPTION, -20202); -- not allowed to use the constant to initialize the exception UNNUMBERED_USEREXCEPTION EXCEPTION; XTEST_NO NUMBER := 0; bogo number; BEGIN DBMS_OUTPUT.ENABLE; <<XCEP_LOOP>> LOOP XTEST_NO := XTEST_NO + 1; DBMS_OUTPUT.PUT_LINE ('Exception test number ' || XTEST_NO); <<INNER_EXCEP_BLK>> BEGIN <<RAISERS>> CASE XTEST_NO WHEN 1 THEN -- triggers ORA-01403, no data found SELECT num_rows INTO BOGO FROM USER_TABLES WHERE 1 = NULL and rownum = 1 ; WHEN 2 THEN RAISE USERRANGE_EXCEPTION; when 3 then RAISE UNNUMBERED_USEREXCEPTION; WHEN 4 THEN DBMS_STANDARD.RAISE_APPLICATION_ERROR (USERRANGE_EXC_NO, 'this is an intentional exception'); else raise_application_error (-20002, 'ran out of exception cases!'); END CASE RAISERS; EXCEPTION WHEN NO_DATA_FOUND THEN DBMS_OUTPUT.PUT_LINE ('[INNER] no data found exception: sqlcode ' || SQLCODE || ', message ' || sqlerrm ); WHEN USERRANGE_EXCEPTION THEN DBMS_OUTPUT.PUT_LINE ('[INNER] user-range exception: sqlcode ' || SQLCODE || ', message ' || sqlerrm ); WHEN UNNUMBERED_USEREXCEPTION THEN DBMS_OUTPUT.PUT_LINE ('[INNER] unnumbered exception: sqlcode ' || SQLCODE || ', message ' || SQLERRM ); WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('[INNER] exception: sqlcode ' || SQLCODE || ', message ' || SQLERRM ); EXIT XCEP_LOOP; --<<<< THIS IS A PRETTY USEFUL APPLICATION OF PL/SQL BLOCK LABELS end inner_excep_blk; END LOOP XCEP_LOOP; DBMS_OUTPUT.PUT_LINE ('Ending exception test and demo block'); EXCEPTION WHEN OTHERS THEN DBMS_OUTPUT.PUT_LINE ('EXCEPTION: ' || SQLERRM); END DEMO_AND_TEST_EXCEPTIONS; / |
anonymous block completed Exception test number 1 [INNER] no data found exception: sqlcode 100, message ORA-01403: no data found Exception test number 2 [INNER] user-range exception: sqlcode -20202, message ORA-20202: Exception test number 3 [INNER] unnumbered exception: sqlcode 1, message User-Defined Exception Exception test number 4 [INNER] user-range exception: sqlcode -20202, message ORA-20202: this is an intentional exception Exception test number 5 [INNER] exception: sqlcode -20002, message ORA-20002: ran out of exception cases! Ending exception test and demo block |
- You can define your own exceptions practically however you like
- PRAGMA_EXCEPTION_INIT will associate ORA- numbers with your own exception names
- you can use this to throw exceptions with a certain number
- you can use this to catch exceptions expecting a certain number
- The implicitly-included package DBMS_STANDARD pre-defines a few dozen exception codes, for example here we have used NO_DATA_FOUND
- If you throw a named exception using RAISE (Oracle predefined or your own), you can't add a message
- To pass a message along on an exception, you must use RAISE_APPLICATION_ERROR.
- not many people use <<BLOCK_NAME>> to name blocks at all, let alone as aggressively as I have in this example. It is completely optional and frankly it rarely helps. I use the following labels:
- DEMO_AND_TEST_EXCEPTIONS
- XCEP_LOOP
- INNER_EXCEP_BLK
- RAISERS