Exceptions can occur due to
1. Some unhandled conditions or data issues which result in oracle throwing an exception(example - query fetching more than the requested number of rows in the into clause)
2. They may be due to some functional misbehavior due to which you want to handle the exception gracefully and throw the user an appropriate message
3. Some business validation needs to be addressed. Example - If the premium payment from a customer is overdue, you may want to stop further processing for that customer. In that case you can raise the exception and in the exception block this exception can be suitably handled.
These exceptions that occur, can be put in an exception block and handled suitably.
Below are some of the different ways of handling exceptions in oracle.
Example 1
Selecting a row from a table where no data exists for the particular record will result in the below error.
ORA-01403: no data found
ORA-06512: at line 10
01403. 00000 - "no data found"
*Cause: No data was found from the objects.
*Action: There was no data from the objects which may be due to end of fetch.
This can be suitably handled in an exception block as shown below.
DECLARE
v_employee_id NUMBER;
v_employee_name VARCHAR2(100);
v_job_id VARCHAR2(10);
BEGIN
v_employee_id := 1025;
SELECT FIRST_NAME || ' ' || LAST_NAME, JOB_ID
INTO v_employee_name, v_job_id
FROM EMPLOYEES WHERE EMPLOYEE_ID = v_employee_id;
EXCEPTION
WHEN NO_DATA_FOUND
THEN
dbms_output.put_line('Data does not exist in EMPLOYEES table for employee_id :' || v_employee_id);
END;
Example 2
Another way of handling an exception would be to raise an user defined exception as below.
DECLARE
book_overdue EXCEPTION;
v_issue_date DATE;
v_due_date DATE;
BEGIN
v_due_date := TO_DATE('28-DEC-2016','DD-MON-RRRR');
v_issue_date := SYSDATE - 15;
IF SYSDATE > v_due_date
THEN
RAISE book_overdue;
END IF;
EXCEPTION
WHEN book_overdue
THEN
dbms_output.put_line('Book is overdue');
END;
Example 3
For Oracle exceptions that do not have a pre defined exception name, you can use the OTHERS exception or give your own exception name.
We can do this using EXCEPTION_INIT.ORA-01422: exact fetch returns more than requested number of rows
ORA-06512: at line 10
01422. 00000 - "exact fetch returns more than requested number of rows"
*Cause: The number specified in exact fetch is less than the rows returned.
*Action: Rewrite the query or change number of rows requested
The oracle code for this error is -1422.
To associate a name to this particular error code, we need to declare the exception as follows
exact_fetch_error EXCEPTION; -- define the exception
PRAGMA EXCEPTION_INIT(exact_fetch_error, -1422); -- associate a code to this exception using EXCEPTION_INIT
Sample Code is shown below
DECLARE
exact_fetch_error EXCEPTION;
PRAGMA EXCEPTION_INIT(exact_fetch_error, -1422);
v_job_id VARCHAR2(100);
BEGIN
SELECT
JOB_ID
INTO
v_job_id
FROM HR.JOB_HISTORY
WHERE EMPLOYEE_ID = 101;
EXCEPTION
WHEN exact_fetch_error
THEN
dbms_output.put_line('Exact fetch returned more than requested number or row.');
END;
Similarly, user defined exceptions can be associated with user defined exception codes.
These codes should be in the range of -20000 and -20999.
Example - you want to handle a divide by zero condition
divide_by_zero EXCEPTION;
PRAGMA EXCEPTION_INIT(divide_by_zero, -20101);
The procedure RAISE_APPLICATTION_ERROR lets you propogate an exception caught in a PL/SQL block gracefully to the application thus avoiding any unhandled exceptions. RAISE_APPLICATION_ERROR is also useful in propogating the error up the hierarchy of PL/SQL functions/procedures where it can be suitably handled. create or replace PROCEDURE P2
AS
v_error_msg VARCHAR2(500);
v_return NUMBER;
BEGIN
BEGIN
v_return := 1/0;
EXCEPTION
WHEN OTHERS THEN
--Propogate the exception to the calling exception block
v_error_msg := 'Exception in P2: Propogate the message to calling block ';
RAISE_APPLICATION_ERROR(-20002, v_error_msg || ' : ' || SQLERRM);
END;
END;
create or replace PROCEDURE P1
AS
v_error_msg VARCHAR2(500);
v_p_flag VARCHAR2(1) := 1;
v_return NUMBER;
BEGIN
v_p_flag := 2;
IF v_p_flag = 1
THEN
v_return := 1/0;
END IF;
IF v_p_flag = 2
THEN
BEGIN
P2;
EXCEPTION
WHEN OTHERS THEN
--Propogate the exception to main exception block
v_error_msg := 'Propogate the message to the main block ';
RAISE_APPLICATION_ERROR(-20001, v_error_msg || ' : ' || SQLERRM);
ROLLBACK;
END;
END IF;
COMMIT;
EXCEPTION
WHEN OTHERS THEN
v_error_msg := 'Exception IN P1 ';
-- All error messages can be logged in this final exception block.
dbms_output.put_line( v_error_msg || SQLCODE || ' :-' || SQLERRM);
END;
Output exception displayed
Exception in P1 -20001: ORA -20001: Propogate the message to the main block ORA-20002: Exception in P2: Propogate the message to calling block : ORA-01476: divisor is equal to zero.
RAISE_APPLICATION_ERROR has a third parameter which takes input as TRUE/FALSE.
The default value for this parameter is false. If this value is set to TRUE, the error is added to the top of the stack of previous errors. If it is false(the default), the last error replaces the previous errors raised. But it has the entire error stack appended in a single line as shown above. DUP_VAL_ON_INDEX - 00001 - when you attempt to store a record in a table with a column that is having an unique index
INVALID_NUMBER - 01722 - the conversion of a character sting into a number fails because the string variable does not contain a valid number
NO_DATA_FOUND - 01403 - when a select from the database does not fetch any records
TOO_MANY_ROWS - 01422 - a select into returns more than one row
ZERO_DIVIDE - 01476 - when a numeric expression has a value 0 in the divisor.
CASE_NOT_FOUND - ORA-06592 - When a particular case condition is not handled and there is no ELSE condition for default values
References https://www.tutorialspoint.com/plsql/plsql_exceptions.htm
No comments:
Post a Comment