Exception Handling in PL/SQL
An exception is an error which disrupts the normal flow of program instructions. PL/SQL provides us the exception block which raises the exception thus helping the programmer to find out the fault and resolve it.
There are two types of exceptions defined in PL/SQL
- User defined exception.
- System defined exceptions.
Syntax to write an exception
WHEN exception THEN statement;
DECLARE
declarations section;BEGIN
executable command(s);EXCEPTION
WHEN exception1 THEN
statement1;
WHEN exception2 THEN
statement2;
[WHEN others THEN]
/* default exception handling code */END;
Note:
When other keyword should be used only at the end of the exception handling block as no exception handling part present later will get executed as the control will exit from the block after executing the WHEN OTHERS.
- System defined exceptions:
These exceptions are predefined in PL/SQL which get raised WHEN certain database rule is violated.
System-defined exceptions are further divided into two categories:- Named system exceptions.
- Unnamed system exceptions.
- Named system exceptions: They have a predefined name by the system like ACCESS_INTO_NULL, DUP_VAL_ON_INDEX, LOGIN_DENIED etc. the list is quite big.
So we will discuss some of the most commonly used exceptions:
Lets create a table geeks.
create table geeks(g_id int , g_name varchar(20), marks int); insert into geeks values(1, 'Suraj',100); insert into geeks values(2, 'Praveen',97); insert into geeks values(3, 'Jessie', 99);
- NO_DATA_FOUND: It is raised WHEN a SELECT INTO statement returns no rows. For eg:
DECLARE
temp
varchar
(20);
BEGIN
SELECT
g_id
into
temp
from
geeks
where
g_name=
'GeeksforGeeks'
;
exception
WHEN
no_data_found
THEN
dbms_output.put_line(
'ERROR'
);
dbms_output.put_line(
'there is no name as'
);
dbms_output.put_line(
'GeeksforGeeks in geeks table'
);
end
;
Output:
ERROR there is no name as GeeksforGeeks in geeks table
- TOO_MANY_ROWS:It is raised WHEN a SELECT INTO statement returns more than one row.
DECLARE
temp
varchar
(20);
BEGIN
-- raises an exception as SELECT
-- into trying to return too many rows
SELECT
g_name
into
temp
from
geeks;
dbms_output.put_line(
temp
);
EXCEPTION
WHEN
too_many_rows
THEN
dbms_output.put_line(
'error trying to SELECT too many rows'
);
end
;
Output:
error trying to SELECT too many rows
- VALUE_ERROR:This error is raised WHEN a statement is executed that resulted in an arithmetic, numeric, string, conversion, or constraint error. This error mainly results from programmer error or invalid data input.
DECLARE
temp
number;
BEGIN
SELECT
g_name
into
temp
from
geeks
where
g_name=
'Suraj'
;
dbms_output.put_line(
'the g_name is '
||
temp
);
EXCEPTION
WHEN
value_error
THEN
dbms_output.put_line(
'Error'
);
dbms_output.put_line(
'Change data type of temp to varchar(20)'
);
END
;
Output:
Error Change data type of temp to varchar(20)
- ZERO_DIVIDE = raises exception WHEN dividing with zero.
DECLARE
a
int
:=10;
b
int
:=0;
answer
int
;
BEGIN
answer:=a/b;
dbms_output.put_line(
'the result after division is'
||answer);
exception
WHEN
zero_divide
THEN
dbms_output.put_line(
'dividing by zero please check the values again'
);
dbms_output.put_line(
'the value of a is '
||a);
dbms_output.put_line(
'the value of b is '
||b);
END
;
Output:
dividing by zero please check the values again the value of a is 10 the value of b is 0
- NO_DATA_FOUND: It is raised WHEN a SELECT INTO statement returns no rows. For eg:
- Unnamed system exceptions:Oracle doesn’t provide name for some system exceptions called unnamed system exceptions.These exceptions don’t occur frequently.These exceptions have two parts code and an associated message.
The way to handle to these exceptions is to assign name to them using Pragma EXCEPTION_INIT
Syntax:PRAGMA EXCEPTION_INIT(exception_name, -error_number);
error_number are pre-defined and have negative integer range from -20000 to -20999.
Example:
DECLARE
exp exception;
pragma exception_init (exp, -20015);
n
int
:=10;
BEGIN
FOR
i
IN
1..n LOOP
dbms_output.put_line(i*i);
IF i*i=36
THEN
RAISE exp;
END
IF;
END
LOOP;
EXCEPTION
WHEN
exp
THEN
dbms_output.put_line(
'Welcome to GeeksforGeeks'
);
END
;
Output:
1 4 9 16 25 36 Welcome to GeeksforGeeks
- User defined exceptions:
This type of users can create their own exceptions according to the need and to raise these exceptions explicitly raise command is used.Example:
- Divide non-negative integer x by y such that the result is greater than or equal to 1.
From the given question we can conclude that there exist two exceptions
- Division be zero.
- If result is greater than or equal to 1 means y is less than or equal to x.
DECLARE
x
int
:=&x; /*taking value
at
run
time
*/
y
int
:=&y;
div_r
float
;
exp1 EXCEPTION;
exp2 EXCEPTION;
BEGIN
IF y=0
then
raise exp1;
ELSEIF y > x
then
raise exp2;
ELSE
div_r:= x / y;
dbms_output.put_line(
'the result is '
||div_r);
END
IF;
EXCEPTION
WHEN
exp1
THEN
dbms_output.put_line(
'Error'
);
dbms_output.put_line(
'division by zero not allowed'
);
WHEN
exp2
THEN
dbms_output.put_line(
'Error'
);
dbms_output.put_line(
'y is greater than x please check the input'
);
END
;
Input 1: x = 20 y = 10 Output: the result is 2
Input 2: x = 20 y = 0 Output: Error division by zero not allowed
Input 3: x=20 y = 30 Output:<.em> Error y is greater than x please check the input
RAISE_APPLICATION_ERROR:
It is used to display user-defined error messages with error number whose range is in between -20000 and -20999. When RAISE_APPLICATION_ERROR executes it returns error message and error code which looks same as Oracle built-in error.Example:
DECLARE
myex EXCEPTION;
n NUMBER :=10;
BEGIN
FOR
i
IN
1..n LOOP
dbms_output.put_line(i*i);
IF i*i=36
THEN
RAISE myex;
END
IF;
END
LOOP;
EXCEPTION
WHEN
myex
THEN
RAISE_APPLICATION_ERROR(-20015,
'Welcome to GeeksForGeeks'
);
END
;
Output:
Error report: ORA-20015: Welcome to GeeksForGeeks ORA-06512: at line 13 1 4 9 16 25 36
Note: The output is based on Oracle Sql developer, the output order might change IF you’re running this code somewhere else.
Scope rules in exception handling:
- We can’t DECLARE an exception twice but we can DECLARE the same exception in two dIFferent blocks.
- Exceptions DECLAREd inside a block are local to that block and global to all its sub-blocks.
As a block can reference only local or global exceptions, enclosing blocks cannot reference exceptions DECLAREd in a sub-block.
If we reDECLARE a global exception in a sub-block, the local declaration prevails i.e. the scope of local is more.Example:
DECLARE
GeeksforGeeks EXCEPTION;
age NUMBER:=16;
BEGIN
-- sub-block BEGINs
DECLARE
-- this declaration prevails
GeeksforGeeks EXCEPTION;
age NUMBER:=22;
BEGIN
IF age > 16
THEN
RAISE GeeksforGeeks; /* this
is
not
handled*/
END
IF;
END
;
-- sub-block ends
EXCEPTION
-- Does not handle raised exception
WHEN
GeeksforGeeks
THEN
DBMS_OUTPUT.PUT_LINE
(
'Handling GeeksforGeeks exception.'
);
WHEN
OTHERS
THEN
DBMS_OUTPUT.PUT_LINE
(
'Could not recognize exception GeeksforGeeks in this scope.'
);
END
;
Output:
Could not recognize exception GeeksforGeeks in this scope.
- Divide non-negative integer x by y such that the result is greater than or equal to 1.
Advantages:
- Exception handling is very useful for error handling, without it we have to issue the command at every point to check for execution errors:
Example:Select .. .. check for 'no data found' error Select .. .. check for 'no data found' error Select .. .. check for 'no data found' error
Here we can see that it is not robust as error processing is not separated from normal processing and IF we miss some line in the code than it may lead to some other kind of error.
- With exception handling we handle errors without writing statements multiple times and we can even handle dIFferent types of errors in one exception block:
Example:BEGIN SELECT ... SELECT ... SELECT ... . . . exception WHEN NO_DATA_FOUND THEN /* catches all 'no data found' errors */ ... WHEN ZERO_DIVIDE THEN /* different types of */ WHEN value_error THEN /* errors handled in same block */ ...
From above code we can conclude that exception handling
- Improves readability by letting us isolate error-handling routines and thus providing robustness.
- Provides reliability, instead of checking for dIFferent types of errors at every point we can simply write them in exception block and IF error exists exception will be raised thus helping the programmer to find out the type of error and eventually resolve it.
Uses: One of the real lIFe use of exception can be found in online train reservation system.
While filling the station code to book the ticket IF we input wrong code it shows us the exception that the code doesn’t exist in database.
Reference: You can find the list of all pre-defined exception here.
Total number of pre-defined exceptions