Exception
Handling in PL/SQL
An
exception is an error situation which may arise during program execution
PLSQL
supports Oracle named (predefined) and unnamed (not predefined) exceptions as
well as user-defined exceptions
In
any type of Exception, when the exception takes place the exception is said to
be “RAISED”
An
Exception Handler is used to specify the response for a raised exception
When
an exception is raised, either implicitly or explicitly, the normal execution
of the program is abandoned
The
control then shifts to the corresponding exception handler if it is present
else control shifts to the calling environment
In
any case, when an exception is fired then the control can not return to the
executable section of the current block
If
an exception is handled then the program unit is considered as successful i. e.
the effect of the operations performed before the exception is raised, is saved
else the earlier operations are rolled back
If
an exception is raised in the executable section and there is an associated
handler, the exception is trapped (handled)
Handlers
for various exceptions can be specified in the EXCEPTION section
A
handler for an exception is of the form
WHEN exception_name THEN
a sequence of statements
Example
EXCEPTION
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('WRONG INPUT');
END;
Types
of Exceptions
Named
(predefined) Oracle Exceptions
Unnamed
(Not predefined) Oracle Exceptions
User-defined
Exceptions
Named
Exceptions
Oracle
has around 20 named predefined
exceptions
Trapped
within the Exception handling block
Some
commonly encountered oracle named exceptions:
NO_DATA_FOUND
– fired when SELECT INTO statement does not return any row
TOO_MANY_ROWS
- fired when SELECT INTO statement returns more than one row
INVALID_CURSOR
– fired when trying to FETCH from a cursor that is not open
ZERO_DIVIDE
– fired when trying to divide by zero
VALUE_ERROR
– fired when trying to put an incompatible value in a variable or column
Raising
an Exception
An
exception is raised implicitly if any Oracle error occurs e. g. when no rows
are retrieved by SELECT statement, PL/SQL raises the exception NO_DATA_FOUND
We
raise an exception explicitly by issuing the RAISE statement within the block
Exception
Handling: Example
DECLARE
myname VARCHAR2 (8);
BEGIN
SELECT ename
INTO myname
FROM emp
WHERE empno = &eno;
DBMS_OUTPUT.put_line
('Name of the employee : ' || myname);
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line
('WRONG EMPLOYEE NUMBER');
WHEN VALUE_ERROR
THEN
DBMS_OUTPUT.put_line
(' Employee Name size larger
than 8');
END;
/
The
OTHERS Handler
Most
of the times Exceptions occur because of inappropriate values passed for user
inputs
In
a good program the probable exceptions are visualized and handled
However
for a program, one may not be able to visualize all the probable exceptions
Handling
all possible exceptions may make the program very bulky
To
overcome this problem a “General Exception Handler” named “OTHERS” is provided
by PL/SQL
The
handler OTHERS traps exceptions not handled in the other handlers in the
exception handling section of the block
Thus
in a program separate handlers are written for those named exceptions, that
require some specific actions to be taken when the exception is fired while for
all the remaining exceptions, the general OTHERS handler is used
Guidelines
for Trapping Exceptions
WHEN
OTHERS should be put up as the last handler
Handlers
for several exceptions can be included in a single block but for a single
exception only one handler can be written
At
a time, there can be only one active exception
Various
Predefined Named Exceptions: Example
DECLARE
myjob emp.job%TYPE;
emprec emp%ROWTYPE;
BEGIN
myjob := '&myJob';
SELECT *
INTO emprec
FROM emp
WHERE UPPER (job) = UPPER (myjob);
DBMS_OUTPUT.put_line
(emprec.ename || ' has salary ' || emprec.sal);
EXCEPTION
-- Various error handlers for
predefined named exceptions
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line
('The job does not exist');
WHEN TOO_MANY_ROWS
THEN
DBMS_OUTPUT.put_line
('More than one employee with
the job');
/* The handler OTHERS traps
exceptions not handled in the other handlers in the exception handling
section*/
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line
('Other error ');
END;
/
Functions
for Trapping Error Code and Message
There
are two built-in functions which can be used to find out which exception
occurred during an execution of a program unit
SQLCODE
Returns the error number of the
corresponding Oracle error that was raised
Returns 1 for user-defined exception
SQLERRM
Returns the error message associated
with the given error number
Returns “USER DEFINED EXCEPTION” for
user-defined exceptions
SQLCODE
and SQLERRM: Example
CREATE TABLE ERRORS (
ercode NUMBER,
ermessage VARCHAR2(512));
DECLARE
v_code NUMBER;
v_errm VARCHAR2 (512);
myno NUMBER (1);
BEGIN
myno := '&myNo';
EXCEPTION
WHEN OTHERS
THEN
v_code := SQLCODE;
v_errm := SQLERRM (SQLCODE);
DBMS_OUTPUT.put_line
(SQLERRM);
INSERT INTO ERRORS
VALUES (v_code, v_errm);
END;
/
Note:
SQLCODE and SQLERRM being procedural statements can not be directly used inside
SQL statement; hence their values are assigned to variables first and then used
in INSERT statement
Unnamed
Oracle Exceptions
Unnamed
exceptions can be trapped by using OTHERS handler
Unnamed
exceptions can be handled by PRAGMA EXCEPTION_INIT which tells the
compiler
to associate an exception name with an oracle error number
PRAGMA
keyword signifies that the statement is a compiler directive, which is not
processed when the PL/SQL block is executed
PRAGMA
EXCEPTION_INIT: Example
DECLARE
e_emp_exist EXCEPTION;
--Naming non-predefined oracle error
PRAGMA EXCEPTION_INIT (e_emp_exist, -2292);
v_deptno dept.deptno%TYPE := &dno;
BEGIN
DELETE FROM dept
WHERE deptno = v_deptno;
COMMIT;
EXCEPTION
WHEN e_emp_exist
THEN
DBMS_OUTPUT.put_line
('Can not delete dept Employees exist');
END;
User-defined
Exceptions
Declared
in the Declare Section with data type as EXCEPTION
Raised
Explicitly by using the RAISE keyword
Handled
in the Exception Section
Local
to a PL/SQL block
User-defined
Exception: Example
DECLARE
-- Declaring user defined
exception
e_check_sal EXCEPTION;
v_empno emp.empno%TYPE := &empno;
emp_sal emp.sal%TYPE := &empsal;
mgr_sal emp.sal%TYPE;
BEGIN
SELECT e1.sal
INTO mgr_sal
FROM emp e, emp e1
WHERE e.mgr = e1.empno AND e.empno = v_empno;
IF (emp_sal >
mgr_sal)
THEN
RAISE e_check_sal; -- Raising user-defined
exception
ELSE
UPDATE emp
SET sal = emp_sal
WHERE empno = v_empno;
END IF;
DBMS_OUTPUT.put_line
('Salary updated');
COMMIT;
EXCEPTION
--Handling user defined
exception
WHEN e_check_sal
THEN
DBMS_OUTPUT.put_line
('Employee salary can not be
greater than Manager salary');
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line
(' Wrong input');
END;
Exception
Propagation
Exceptions Raised in the Executable Section
PL/SQL uses the following rule to determine
which exception handler to invoke:
Current
block has a handler for the exception, execute it and complete the block
successfully. Control then passes to the enclosing block.
No
handler for current exception, propagate the exception by raising it in the
enclosing block. Step 1 is executed for the enclosing block. If there is no
enclosing block, the exception will be propagated out to the calling
environment, such as SQL* Plus.
Exceptions Raised in the
Executable Section: Example 1
Exceptions
Raised in the Executable Section: Example 2
Exceptions
Raised in Declarative Section: Example 1
Exceptions
Raised in Declarative Section:Example 2
Exceptions
Raised in Exception Section:Example 1
Example –
Exception Propagation
BEGIN
UPDATE dept
SET loc = 'New1'
WHERE deptno = 10;
DECLARE
myjob emp.job%TYPE := '&myjob';
emprec emp%ROWTYPE;
BEGIN
UPDATE dept
SET loc = 'New2'
WHERE deptno = 20;
SELECT *
INTO emprec
FROM emp
WHERE job = UPPER (myjob);
DBMS_OUTPUT.put_line
(emprec.ename || ' has salary ' || emprec.sal);
EXCEPTION
WHEN NO_DATA_FOUND
THEN
DBMS_OUTPUT.put_line
('The job does not exist');
WHEN TOO_MANY_ROWS
THEN
DBMS_OUTPUT.put_line
('More than one employee with
the job');
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line
('Other error ' || SQLERRM);
END;
UPDATE dept
SET loc = 'New3'
WHERE deptno = 30;
EXCEPTION
WHEN OTHERS
THEN
DBMS_OUTPUT.put_line
('The inner block error is
trapped here as raised in
DECLARE
section'
);
END;
No comments:
Post a Comment