You are on page 1of 6

Database Interaction with PL/SQL: Pre-defined Exceptions

(Page 1 of 4 )

Please note that all the examples in this series have been tested only with Oracle 10g and not
with all the previous versions of Oracle. Refer to the documentation of the respective version
you are using if any programs fail to execute.

Introduction to Exception Handling

Before going to exception handling, let us first determine all the possible ways to get errors.
Errors may occur in PL/SQL (of course, not only PL/SQL) in several possible ways including
hardware failures, network failures, bugs in programs, out of memory and several other
reasons. We may not know which error has been raised at what moment. But we need to
handle all such errors and provide some meaningful messages to the user (instead of making
the user horrified with jargon-filled error messages).

An exception is generally a runtime error which gets raised by PL/SQL runtime when a
PL/SQL block is in the process of execution. Handling the exception consists of trapping the
error (or exception) and providing a meaningful explanation to the user without showing the
weird error message raised by the PL/SQL run-time. This doesn't mean only providing
meaningful explanations; we can take certain actions (programmatically) when an error
occurs at runtime.

Basically, there exist two types of exceptions:

1. Predefined Exceptions

Predefined exceptions are the ones which are already defined by Oracle team that
correspond to the most common oracle errors (like division by zero, out of memory,
etc.). We can handle them directly within our program without declaring them, and
we have thousands of such type of exceptions. In this article, I cover the most
important ones.

2. User-Defined Exceptions

User-Defined Exceptions must be declared and raised explicitly by the user (by
issuing RAISE statements). These exceptions are created, used, raised and
implemented by user himself. Oracle will not know about any of those exceptions (till
it finds the declarations of those exceptions within the PL/SQL block). There exists
EXCEPTION section within the PL/SQL block to handle any sort of exceptions and
the section is optional. Let us start by looking into some of the most commonly used
predefined exceptions.

Next: No Data Found, Too Many Rows >>

Database Interaction with PL/SQL: Pre-defined Exceptions - No Data Found, Too


Many Rows
(Page 2 of 4 )
NO_DATA_FOUND

NO_DATA_FOUND exception is raised when SELECT…INTO statement could not find


any row (or value) to fetch into variables.

Let us consider the following example:

Declare
  v_empno emp.empno%Type := &empno;
  v_ename emp.ename%Type;
Begin
  Select ename into v_ename From emp 
  where empno=v_empno;
  dbms_output.put_line('Name: '||v_ename);
Exception
  when no_data_found then
    dbms_output.put_line('Employee not found');
End;

From the above program, we declare two variables 'v_empno' and 'v_ename'. We accept input
from the user just by placing '&empno'. All this happens within declaration section. Within
the body (between 'begin' and 'end'), we fetch the 'ename' and place it in 'v_ename' from the
table 'emp', based on the 'where' condition framed from the user input. To display the value
available in 'v_ename', we use DBMS_OUTPUT.PUT_LINE statement. If employee number
could not be found, it will raise an exception where we need to handle it within the
EXCEPTION section before 'END' statement.

The exception section is used to handle any type of exception. So, we need to specify the
exception (which is to be handled) using WHEN statement within the exception section.
Using DBMS_OUTPUT.PUT_LINE statement we can display the error 'Employee not found'
on to the screen.

The flow of execution of program will be something like the following (in brief):

 Declares the variables and accepts input from the user


 Try to execute the SELECT statement and fetch 'ename' into 'v_ename'
 If SELECT statement gets successfully executed, it displays the employee name (next
line of SELECT) and directly jumps to END (skipping the exception section).
 If SELECT statement could not retrieve any row (in this case it is 'ename'), it
immediately jumps to exception section (skipping the DBMS_OUTPUT statement
next to SELECT statement) and checks whether the exception (or error) is
NO_DATA_FOUND or not. If so, displays the message 'Employee not found'.

TOO_MANY_ROWS

Now that we understood about NO_DATA_FOUND, we shall look into


TOO_MANY_ROWS. We all know very well that SELECT..INTO statement will not be
able to retrieve more than one row. So, when a SELECT ….INTO statement in a PL/SQL
blocks tries to return more than one row, TOO_MANY_ROWS exception gets raised. Let us
consider the following program.
Declare
  v_emp emp%rowtype;
  v_Sal emp.sal%Type := &sal;
Begin
  Select * into v_emp From emp
  where sal=v_sal;
  dbms_output.put_line('Name:'||v_emp.ename);
Exception
  When Too_Many_rows then
    dbms_output.put_line('More than one employee having same salary');
End ;

The above program is very similar to the first program, and the flow of execution of program
will be something like the following (in brief):

 Declares the variables and accepts input from the user


 Try to execute the SELECT statement and fetch entire row from 'emp' into 'v_emp'
 If SELECT statement gets successfully executed with only single row, it displays the
employee name (next line of SELECT) and directly jumps to END (skipping the
exception section).
 If SELECT statement is trying to get more than one row (as there exists a possibility
of having more than one employee with the same salary given), it immediately jumps
to exception section (skipping the DBMS_OUTPUT statement next to SELECT
statement) and checks whether the exception (or error) is TOO_MANY_ROWS or
not. If so, displays the message 'More than one employee having same salary'.

Next: Dup Val on Index, Zero Divide, Invalid Number, Value Error >>

Database Interaction with PL/SQL: Pre-defined Exceptions - Dup Val on Index, Zero
Divide, Invalid Number, Value Error
(Page 3 of 4 )

DUP_VAL_ON_INDEX

This is bit different from the above two exceptions. This exception is not at all related to
SELECT..INTO statement (as above exceptions). This exception gets raised when you try to
update (or even insert) a row with a duplicate value in to a column constrained by a unique
index (obviously Primary key as well). Let us consider the following program.

Declare
  v_empno emp.empno%type:=&empno;
  v_ename emp.ename%type:='&ename';
  v_deptno emp.deptno%type:=&deptno;
Begin
  Insert into emp(empno,ename,deptno)
  Values (v_empno,v_ename,v_deptno);
  dbms_output.put_line('Employee Successfully Inserted');
Exception
  When DUP_VAL_ON_INDEX then
    dbms_output.put_line('Employee ID already exists');
End ;

The flow of execution of program will be something like the following:

 Declares the variables and accepts input from the user


 Tries to execute the INSERT statement based on the values provided by user
 If INSERT statement gets successfully executed, it displays a positive message to user
that the row has been inserted and directly jumps to END statement (skipping the
exception section).
 If INSERT fails due to duplication in a column, constrained with unique index (or
primary key), it immediately jumps to exception section (skipping the
DBMS_OUTPUT statement next to INSERT statement) and checks whether the
exception (or error) is DUP_VAL_ON_INDEX or not. If so, displays the message
'Employee ID already exists'.

ZERO_DIVIDE, INVALID_NUMBER, VALUE_ERROR

The above two predefined exceptions worked well with SELECT..INTO statement. But some
predefined exceptions may not be related to SELECT..INTO statement. Let us see
ZERO_DIVIDE, INVALID_NUMBER and VALUE_ERROR together within this section.

No number can be divided with zero as it results in infinite. To handle such type of situation,
there exists ZERO_DIVIDE exception. Let us consider the following example.

Declare
  x number := &x;
  y number := &y;
  z number;
Begin
  z := x/y;
  dbms_output.put_line ('Result: ' || z);
Exception
  When ZERO_DIVIDE then
    dbms_output.put_line ('Division by zero occured');
End ;

The above program illustrates simple variable declarations of numeric data type . Here, we
declare three variables (x, y and z). The values of variables 'x' and 'y' are accepted from the
user. Observe that all the variables are of type number (any numeric data type is acceptable).
Within the body, we divide 'x' with 'y' and store the result in 'z'.

Everything works fine as long as you provide proper values. If you try to provide the value of
'y' as zero, then ZERO_DIVIDE exception gets raised and a message gets displayed to user.

Coming to INVALID_NUMBER, I hope you can easily understand that whenever PL/SQL
runtime is unable to convert a character string to number, the exception gets raised. The
following example demonstrates the same.
Declare
  v_empno varchar2(4):='&empno';
  v_ename varchar2(20):='&ename';
  v_deptno varchar2(2):='&deptno';
Begin
  Insert into emp(empno,ename,deptno)
  Values (v_empno,v_ename,v_deptno);
Exception
  When INVALID_NUMBER then
     dbms_output.put_line('Given Employee Number or deptno is Invalid');
End ;

Coming to VALUE_ERROR, this is almost similar to INVALID_NUMBER except that it


works with almost any data type. INVALID_NUMBER gets raised only when SQL
statement is issued whereas VALUE_ERROR gets raised with PL/SQL statements. Let us go
through the following example.

Declare
  z number;
Begin
  z := '&x' + '&y';
  dbms_output.put_line ('Result: ' || z);
Exception
  When VALUE_ERROR then
    dbms_output.put_line ('Invalid values');
End ;

The above program accepts the value of 'x' and 'y' in the form of character strings and
implicitly converts them to numeric. If user provides a non-numeric value, the
VALUE_ERROR gets raised. In this case, INVALID_NUMBER will not be raised as
nothing is related with SQL statement.

Next: A Word About OTHERS Exception >>

Database Interaction with PL/SQL: Pre-defined Exceptions - A Word About OTHERS


Exception
(Page 4 of 4 )

This is a great exception which can handle almost any type of exception within PL/SQL. In
general this exception is used when you are not sure about any specific error which may raise
within PL/SQL block. But you are suggested to use this exception caution. This exception is
very frequently used for log eventing or auditing. The following example illustrates usage of
this exception.

Declare
  v_empno emp.empno%type:=&empno;
  v_ename emp.ename%type:='&ename';
  v_deptno emp.deptno%type:=&deptno;
Begin
  Insert into emp(empno,ename,deptno)
  Values (v_empno,v_ename,v_deptno);
  dbms_output.put_line('Employee Successfully Inserted');
Exception
  When OTHERS then
    dbms_output.put_line('An error occurred. Please check your values');
End ;

You should also observe from the above example that the error message is also bit generic
rather than confirming to only one scenario (like previous example). It is suggested to
provide a generic error message within OTHERS exception, as you may not know any
specific error which may occur.

You might also like