Exception
Exception
EXCEPTION
Exception means departure from expected result.
Any error or problem which handled and continues to work normally.
Exception can be defined as the state of an entity, which is different from its conventional and normal
behavior. In context to programming language, exception refers to the abnormal situation in the normal
flow of the program. Oracle server raises exception whenever it encounters a logical violation of the flow
during program execution.
I have listed the common situations which end up raising exceptions and subsequently termination of the
program.
Coding mistakes
Hardware failures
The figure below shows the program flow, which is followed when an exception situation occurs in the
PL/SQL block and the exception has been handled. Once the exception has been raised and trapped, and
the control moves to EXCEPTION section, the program propagates in the forward direction.
If the exception has not been handled, the program terminates abruptly or propagates to the calling
environment
Exception Handling
Exceptions can be trapped in the EXCEPTION section of a PL/SQL block. Oracle supports two ways to
raise exception in a program, implicitly or explicitly.
Exceptions which are automatically raised by the oracle server fall under the category of implicit way
raising an exception. PL/SQL runtime engine identifies the abnormal flow and raises the exception. For
example, NO_DATA_FOUND or TOO_MANY_ROWS are the system defined exceptions which are
raised by the server during program execution.
Exceptions which are trapped in executable section and handled in the EXCEPTION block by the
programmer are explicit ways raising exceptions. In this category, a user can either explicitly raise an
already existing system defined exception or create a new exception and invoke in the program.
SYNTAX
EXCEPTION
WHEN exception1 [OR exception2 . . .] THEN
statement1;
statement2;
...
[WHEN exception3 [OR exception4 . . .] THEN
statement1;
statement2;
. . .]
[WHEN OTHERS THEN
statement1;
statement2;
. . .]
/
DECLARE
BEGIN
<execution block>
.
.
EXCEPTION
WHEN <exceptionl_name>
THEN
<Exception handling code for the “exception 1 _name’' >
WHEN OTHERS
THEN
<Default exception handling code for all exceptions >
END;
/
Oracle uses two built in functions for catching exceptions and getting its information, SQLCODE and
SQLERRM.
SQLCODE returns the error number for the latest occurred exception in the PL/SQL block, while
SQLERRM returns the error message associated with the latter error number.
TYPES OF ERROR
Compile time error
Run time error
DIFFERENCE BETWEEN EXCEPTION & ERROR
EXCEPTION ERROR
The query will return Exception on run time. The query will throw the Error on compile time.
We can able to handle and continue to work. We can rectify and get the exact result.
In function, an exception should always either return value or raise the exception further. else Oracle
will throw 'Function returned without a value' error at run-time.
Transaction control statements can be given at exception handling block.
SQLERRM and SQLCODE are the in-built functions that will give the exception message and code.
If an exception is not handled then by default all the active transaction in that session will be rolled
back.
RAISE_APPLICATION_ERROR (-<error_code>, <error_message>) can be used instead of RAISE to
raise the error with user code and message. Error code should be greater than 20000 and prefixed with
'-'.
Pragma exception_init
Here we can give the name for pre-defined exception.
We can associate named exception with particular oracle error codes.
SQLCODE
Sqlerrm returns current error message and sqlcode returns current error message code.
It will support for all exception types.
PRE-DEFINED EXCEPTION
Oracle has predefined several exceptions like,
DECLARE
--variable
--cursor
Declaring exception
BEGIN
EXCEPTION
--exception handling
END;
As soon as Oracle server encounters any illogical flow in the program flow, it stops further execution of
program, identifies and throws the appropriate exception; program terminates abruptly.
DECLARE
L_DEPTID NUMBER := 10;
L_ENAME VARCHAR2(100);
L_SAL NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before SQL query');
SELECT EMPLOYEE_NAME,SALARY
INTO L_ENAME, L_SAL
FROM EMPLOYEES
WHERE DEPARTMENT_ID = L_DEPTID;
A developer can explicitly raise the system defined exceptions. In the Code [], the TOO_MANY_ROWS
exception can be captured by defining an exception handler in the EXCEPTION section.
DECLARE
L_DEPTID NUMBER := 10;
L_ENAME VARCHAR2(100);
L_SAL NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before SQL query');
SELECT EMPLOYEE_NAME,SALARY
INTO L_ENAME, L_SAL
FROM EMPLOYEES
WHERE DEPARTMENT_ID = L_DEPTID;
DBMS_OUTPUT.PUT_LINE('After SQL query');
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE ('Use Oracle Bulk Collect feature or Cursor to select multiple rows from
a table');
END;
/
Table created.
no rows selected
DECLARE
i NUMBER(10);
BEGIN
SELECT salary INTO i
FROM t1;
dbms_output.put_line(i);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('There is no data inside the table');
END;
/
There is no data inside the table
DECLARE
L_DEPTID NUMBER := 15;
L_ENAME VARCHAR2(100);
L_SAL NUMBER;
CURSOR C IS
SELECT EMPLOYEE_NAME,SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = L_DEPTID;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before SQL query');
OPEN C;
FETCH C INTO L_ENAME, L_SAL;
IF C%ROWCOUNT = 0 THEN
RAISE NO_DATA_FOUND;
END IF;
CLOSE C;
DBMS_OUTPUT.PUT_LINE('After SQL query');
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE ('No Employees in the department');
END;
/
DECLARE
v_nm Employees.first_name%TYPE;
BEGIN
SELECT
first_name
INTO
v_nm
FROM
employees
WHERE
first_name='sasik';
dbms_output.put_line('The name is :'||v_nm);
EXCEPTION
WHEN no_data_found THEN
dbms_output.put_line('Please enter the valid name');
END;
/
Please enter the valid name
DECLARE
L_DEPTID NUMBER := 10;
L_ENAME VARCHAR2(100);
L_SAL NUMBER;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before SQL query');
SELECT EMPLOYEE_NAME,SALARY
INTO L_ENAME, L_SAL
FROM EMPLOYEES
WHERE DEPARTMENT_ID = L_DEPTID;
DBMS_OUTPUT.PUT_LINE('After SQL query');
EXCEPTION
WHEN TOO_MANY_ROWS THEN
DBMS_OUTPUT.PUT_LINE ('Use Oracle Bulk Collect feature or Cursor to select multiple rows from
a table');
END;
/
DECLARE
v_salary NUMBER(10);
BEGIN
SELECT
salary
INTO
v_salary
FROM
employees
WHERE
salary=17000;
dbms_output.put_line('The salary is :'||v_salary);
EXCEPTION
WHEN too_many_rows THEN
dbms_output.put_line('Please declare explicit cursor');
WHEN no_data_found THEN
dbms_output.put_line('Please enter the valid data');
END;
/
Please declare explicit cursor
FIRST_NAME SALARY
-------------------- ----------
Neena 17000
Lex 17000
2 rows selected.
DUP_VAL_ON_INDEX
SQL> CREATE TABLE t1
2 (
3 id NUMBER(10),
4 CONSTRAINT t1_id_pk PRIMARY KEY(id)
5 );
Table created.
1 row created.
1 row selected.
DECLARE
i NUMBER(10);
BEGIN
INSERT INTO t1 VALUES(7000);
EXCEPTION
WHEN dup_val_on_index THEN
dbms_output.put_line('Id already exist');
END;
/
Id already exist
User defined exceptions allow the developers to create their own customized exceptions and raise them
within the program wherever required. They are declared in the DECLARE section of the block with type
as EXCEPTION and raised using RAISE statement.
In Oracle, other than the above-predefined exceptions, the programmer can create their own exception and
handle them. They can be created at a subprogram level in the declaration part. These exceptions are
visible only in that subprogram. The exception that is defined in the package specification is public
exception, and it is visible wherever the package is accessible.
SYNTAX
DECLARE
<exception_name> EXCEPTION;
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
DECLARE
i CHAR(1):='M';
GENDER_ERROR EXCEPTION;
BEGIN
IF i NOT IN ('M','F') THEN
raise gender_error;
END IF;
dbms_output.put_line('The gender is :'||i);
EXCEPTION
WHEN gender_error THEN
dbms_output.put_line('Invalid option please enter (M/F)');
END;
/
The gender is :M
DECLARE
L_DEPTID NUMBER := 15;
L_ENAME VARCHAR2(100);
L_SAL NUMBER;
LOCAL_EXCEPTION EXCEPTION;
CURSOR C IS
SELECT EMPLOYEE_NAME,SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = L_DEPTID;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before SQL query');
OPEN C;
FETCH C INTO L_ENAME, L_SAL;
IF C%ROWCOUNT =0 THEN
RAISE LOCAL_EXCEPTION;
END IF;
CLOSE C;
DBMS_OUTPUT.PUT_LINE('After SQL query');
EXCEPTION
WHEN LOCAL_EXCEPTION THEN
DBMS_OUTPUT.PUT_LINE ('No Employees in the department');
END;
/
DECLARE
i CHAR(1):='f';
GENDER_ERROR EXCEPTION;
BEGIN
IF i NOT IN ('M','F') THEN
raise gender_error;
END IF;
dbms_output.put_line('The gender is :'||i);
EXCEPTION
WHEN gender_error THEN
dbms_output.put_line('Invalid option please enter (M/F)');
END;
/
Invalid option please enter (M/F)
--------------------->>---------------<<----------------------
Oracle facilitates the developer by privileging them to create an error number of their own choice and
associating them with a customized message. RAISE_APPLICATION_ERROR is an Oracle API, which
allows choosing the error numbers in range of -20000 to -20999 and fix them with an error message
All the predefined exceptions are raised implicitly whenever the error occurs. But the user-defined
exception needs to be raised explicitly.
This can be achieved using the keyword 'RAISE'. This can be used in any of the ways mentioned below.
If 'RAISE' is used separately in the program, then it will propagate the already raised exception to the
parent block. Only in exception block can be used as shown below.
SYNTAX
RAISE_APPLICATION_ERROR (error_number, error_message[, {TRUE | FALSE}])
DECLARE
<Variable declaration>
BEGIN
<Execution block>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
RAISE;
END;
/
DECLARE
L_DEPTID NUMBER := 15;
L_ENAME VARCHAR2(100);
L_SAL NUMBER;
CURSOR C IS
SELECT EMPLOYEE_NAME,SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = L_DEPTID;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before SQL query');
OPEN C;
FETCH C INTO L_ENAME, L_SAL;
IF C%ROWCOUNT =0 THEN
RAISE_APPLICATION_ERROR(-20001,' No Employees in the department');
END IF;
CLOSE C;
DBMS_OUTPUT.PUT_LINE('After SQL query');
END;
/
DECLARE
BEGIN
<Execution block>
RAISE <exception_name>
EXCEPTION
WHEN <exception_name> THEN
<Handler>
END;
DECLARE
i CHAR(1):='O';
BEGIN
IF i NOT IN('M','F')THEN
RAISE_APPLICATION_ERROR(-20001,'Try later');
END IF;
dbms_output.put_line(i);
END;
/
DECLARE
*
ERROR at line 1:
ORA-20001: Try later
ORA-06512: at line 5
EXCEPTION
WHEN BELOW_SALARY_RANGE THEN
dbms_output.put_line('Employee ' || n_emp_id ||
' has salary below the salary range');
WHEN ABOVE_SALARY_RANGE THEN
dbms_output.put_line('Employee ' || n_emp_id ||
' has salary above the salary range');
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Employee ' || n_emp_id || ' not found');
END;
/
--------------------->>---------------<<----------------------
USE PRAGMA EXCEPTION_INIT FOR ERROR HANDLING
Associating a User Defined Exception with an Error Number (or Exception Code)
A user defined exception can be associated with an error number using PRAGMA EXCEPTION_INIT.
The pragma is a compiler directive which hints the compiler to accept the directions provided in the
program. The PRAGMA EXCEPTION_INIT directs the compiler to align the user defined exception with
a self assigned error number. The error number must be one of the valid ORA error codes, which are
defined by the server.
SYNTAX
DECLARE
L_DEPTID NUMBER := 15;
L_ENAME VARCHAR2(100);
L_SAL NUMBER;
LOCAL_EXCEPTION EXCEPTION;
PRAGMA EXCEPTION_INIT(LOCAL_EXCEPTION, -100);
CURSOR C IS
SELECT EMPLOYEE_NAME,SALARY
FROM EMPLOYEES
WHERE DEPARTMENT_ID = L_DEPTID;
BEGIN
DBMS_OUTPUT.PUT_LINE('Before SQL query');
OPEN C;
FETCH C INTO L_ENAME, L_SAL;
IF C%ROWCOUNT =0 THEN
RAISE LOCAL_EXCEPTION;
END IF;
CLOSE C;
DBMS_OUTPUT.PUT_LINE('After SQL query');
EXCEPTION
WHEN LOCAL_EXCEPTION THEN
DBMS_OUTPUT.PUT_LINE (‘Exception Error NUMBER:’||SQLCODE);
DBMS_OUTPUT.PUT_LINE ('No Employees in the department');
END;
/
Table dropped.
Table created.
SQL>
SQL> INSERT INTO test_exinit VALUES(1);
1 row created.
ID
----------
1
1 row selected.
SQL> INSERT INTO test_exinit VALUES(null);
INSERT INTO test_exinit VALUES(null)
*
ERROR at line 1:
ORA-01400: cannot insert NULL into ("HR"."TEST_EXINIT"."ID")
DECLARE
not_null EXCEPTION;
PRAGMA EXCEPTION_INIT (not_null,-01400);
BEGIN
INSERT INTO test_exinit VALUES(null);
EXCEPTION
WHEN not_null THEN
dbms_output.put_line('Null values is not allowed');
END;
/
Null values is not allowed
vSqlCode NUMBER;
vSqlErrM VARCHAR2(64);
v_first_name VARCHAR2(30);
BEGIN
SELECT
First_name
INTO
v_first_name
FROM
Employees
WHERE
employee_id = 11;
EXCEPTION
WHEN OTHERS THEN
vSqlCode := SqlCode;
vSqlErrM := Substr(SqlErrM, 1 ,64);
Dbms_Output.Put_Line('Code '||vSqlCode
|| ': ' ||vSqlErrM);
INSERT INTO Errors Values
(
vSqlCode
,vSqlErrM
,SYSTIMESTAMP
);
END;
Code 100: ORA-01403: no data found
DBMS_OUTPUT.put_line (SQLCODE);
DECLARE
aname VARCHAR2(5);
BEGIN
DECLARE
aname VARCHAR2(5) := 'Big String';
BEGIN
DBMS_OUTPUT.PUT_LINE (aname);
EXCEPTION
WHEN VALUE_ERROR
THEN
DBMS_OUTPUT.PUT_LINE ('Inner block');
END;
DBMS_OUTPUT.put_line (SQLCODE);
DBMS_OUTPUT.PUT_LINE ('What error?');
EXCEPTION
WHEN VALUE_ERROR
THEN
DBMS_OUTPUT.PUT_LINE ('Outer block');
END;
/
Outer block
DECLARE
aname VARCHAR2(5);
BEGIN
DECLARE
aname VARCHAR2(5) := 'Justice';
loc INTEGER := 1;
BEGIN
loc := 2;
DBMS_OUTPUT.PUT_LINE (aname);
loc := 3;
DELETE FROM employees;
EXCEPTION
WHEN VALUE_ERROR
THEN
DBMS_OUTPUT.PUT_LINE ('Got as far as ' || loc);
ROLLBACK;
END;
DBMS_OUTPUT.PUT_LINE ('What error?');
ROLLBACK;
EXCEPTION
WHEN VALUE_ERROR
THEN
DBMS_OUTPUT.PUT_LINE ('Outer block');
ROLLBACK;
END;
/
Outer block
BEGIN
<<outer>>
DECLARE
aname VARCHAR2 (5);
BEGIN
<<inner>>
DECLARE
aname VARCHAR2 (20);
BEGIN
OUTER.aname := 'Big String';
EXCEPTION
WHEN VALUE_ERROR
THEN
RAISE NO_DATA_FOUND;
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line ('Inner block');
END INNER;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line ('Outer block');
END OUTER;
END;
/
Outer block
DECLARE
v_totsal NUMBER;
v_ename employees.last_name%TYPE;
BEGIN
/* There are no rows with department_id = -15 */
SELECT SUM (salary) INTO v_totsal
FROM employees
WHERE department_id = -15;
DECLARE
PLS_INTEGER VARCHAR2 (1);
NO_DATA_FOUND EXCEPTION;
BEGIN
SELECT dummy
INTO PLS_INTEGER
FROM DUAL
WHERE 1 = 2;
IF PLS_INTEGER IS NULL
THEN
RAISE NO_DATA_FOUND;
END IF;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line ('No dummy!');
END;
/
ORA-01403: no data found
--------------------->>---------------<<----------------------