Cursors and Exception Handling:
Cursors and Exception Handling:
5.1 Concepts of Cursors
5.1.1 Types of cursors (Implicit & Explicit )
5.1.2 Declare, open, fetch and close cursors.
5.2 Cursor Attributes :
(%FOUND,%NOTFOUND,
%ISOPEN,%ROWCOUNT)
5.3 Exception Handling in PL/SQL
5.3.1 Types of Exceptions:
5.3.1.1 Named System Exceptions
5.3.1.2 Unnamed System
Exceptions
5.3.1.3 User-defined Exceptions
5.3.1.4 User Defined Exceptions
5.3.2 Exception Handling
Cursors and Exception Handling in PL/SQL.
5.1 Concepts of Cursors.
A cursor in PL/SQL is a mechanism that allows processing multiple rows from a query one row at a time.
Since SQL queries return a result set, cursors help in handling this data efficiently within PL/SQL blocks.
PL/SQL provides two types of cursors:
Implicit Cursors – Automatically created by Oracle for
SELECT,INSERT,UPDATE, orDELETEstatements.Explicit Cursors – Manually defined by the programmer to process multiple rows from a query.
5.1.1 Types of Cursors.
1. Implicit Cursors.
Created automatically when a SQL statement executes inside PL/SQL.
Used for
INSERT,UPDATE,DELETE, andSELECT...INTOstatements.No need for explicit declaration, opening, or closing.
Useful when a query returns only one row.
Example of Implicit Cursor:
DECLARE
emp_name employees.name%TYPE;
BEGIN
SELECT name INTO emp_name FROM employees WHERE emp_id = 101;
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_name);
END;
/ Here, Oracle creates an implicit cursor for the
SELECTstatement.The cursor automatically fetches the data and closes itself.
2. Explicit Cursors.
Used when a query returns multiple rows.
Must be declared, opened, fetched, and closed explicitly.
Provides more control over data retrieval.
Example of Explicit Cursor:
DECLARE
CURSOR emp_cursor IS SELECT name FROM employees;
emp_name employees.name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO emp_name;
DBMS_OUTPUT.PUT_LINE('Employee Name: ' || emp_name);
CLOSE emp_cursor;
END;
/ Here, an explicit cursor is created for fetching employee names.
The cursor is manually opened, fetched, and closed.
5.1.2 Cursor Operations (Declare, Open, Fetch, Close)
1. Declaring a Cursor.
A cursor is declared to store a result set of a SQL query.
Declared in the DECLARE section using the
CURSORkeyword.Syntax:
CURSOR cursor_name IS query;
Example:
CURSOR emp_cursor IS SELECT name, salary FROM employees WHERE department = 'IT';
2. Opening a Cursor.
The
OPENstatement allocates memory and executes the query.It does not fetch data yet.
SYNTAX
OPEN cursor_name;
Example:
OPEN emp_cursor;
3. Fetching Data from Cursor.
The
FETCHstatement retrieves one row at a time.Each
FETCHmoves the cursor to the next row.SYNTAX
FETCH cursor_name INTO variable1, variable2, ...;
Example:
FETCH emp_cursor INTO emp_name, emp_salary;
4. Closing a Cursor.
The
CLOSEstatement releases memory used by the cursor.SYNTAX
CLOSE cursor_name;
Example:
CLOSE emp_cursor;
5.2 Cursor Attributes.
| Cursor Attribute | Description |
|---|---|
| %FOUND | Returns TRUE if the last fetch retrieved a row. |
| %NOTFOUND | Returns TRUE if the last fetch failed (no rows left). |
| %ISOPEN | Returns TRUE if the cursor is open. |
| %ROWCOUNT | Returns the number of rows fetched so far. |
1. %FOUND Attribute.
Used to check if a row was successfully fetched.
Example :-
DECLARE
CURSOR emp_cursor IS SELECT name FROM employees;
emp_name employees.name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO emp_name;
IF emp_cursor%FOUND THEN
DBMS_OUTPUT.PUT_LINE('Data found: ' || emp_name);
ELSE
DBMS_OUTPUT.PUT_LINE('No data found');
END IF;
CLOSE emp_cursor;
END;
/ 2. %NOTFOUND Attribute
Used to check if no more rows exist in the result set.
DECLARE
CURSOR emp_cursor IS SELECT name FROM employees;
emp_name employees.name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO emp_name;
IF emp_cursor%NOTFOUND THEN
DBMS_OUTPUT.PUT_LINE('No more records');
ELSE
DBMS_OUTPUT.PUT_LINE('Employee: ' || emp_name);
END IF;
CLOSE emp_cursor;
END;
/ 3. %ISOPEN Attribute
Checks whether the cursor is open or closed.
DECLARE
CURSOR emp_cursor IS SELECT name FROM employees;
BEGIN
OPEN emp_cursor;
IF emp_cursor%ISOPEN THEN
DBMS_OUTPUT.PUT_LINE('Cursor is open');
END IF;
CLOSE emp_cursor;
END;
/ 4. %ROWCOUNT Attribute.
Returns number of rows fetched so far.
DECLARE
CURSOR emp_cursor IS SELECT name FROM employees;
emp_name employees.name%TYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO emp_name;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE('Row ' || emp_cursor%ROWCOUNT || ': ' || emp_name);
END LOOP;
CLOSE emp_cursor;
END;
/ 5.3 Exception Handling in PL/SQL.
Exception handling in PL/SQL allows developers to detect and manage errors that occur during program execution.
It ensures that errors are properly handled without abruptly terminating the execution of a PL/SQL block.
When an error occurs, PL/SQL raises an exception, which can be handled using the
EXCEPTIONblock.Exceptions can be predefined (system-generated) or user-defined.
5.3.1 Types of Exceptions
PL/SQL provides three types of exceptions:
Named System Exceptions (Predefined by Oracle)
Unnamed System Exceptions (Raised by the system but not predefined)
User-Defined Exceptions (Custom exceptions created by the programmer)
5.3.1.1 Named System Exceptions
Oracle provides predefined exceptions for common errors like division by zero or invalid operations.
These exceptions do not need explicit declaration.
| Exception Name | Error Code | Description |
|---|---|---|
| NO_DATA_FOUND | ORA-01403 | Raised when a SELECT INTO statement returns no rows. |
| TOO_MANY_ROWS | ORA-01422 | Raised when a SELECT INTO statement returns more than one row. |
| ZERO_DIVIDE | ORA-01476 | Raised when attempting to divide a number by zero. |
| INVALID_NUMBER | ORA-01722 | Raised when an invalid number is used in an arithmetic operation. |
DECLARE
v_result NUMBER;
BEGIN
v_result := 10 / 0; -- This will cause a division by zero error
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('Error: Division by zero is not allowed');
END;
/
The ZERO_DIVIDE exception is automatically raised and handled in the EXCEPTION block.
5.3.1.2 Unnamed System Exceptions.
Some exceptions are raised by the system but do not have predefined names.
These can be handled using the
WHEN OTHERSclause or by associating them with a custom name using PRAGMA EXCEPTION_INIT.Example.
DECLARE
v_salary NUMBER;
BEGIN
SELECT salary INTO v_salary FROM employees WHERE emp_id = 9999; -- Invalid ID
EXCEPTION
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An error occurred: ' || SQLERRM);
END;
/ The
WHEN OTHERSclause catches any unnamed system exception.SQLERRMretrieves the error message.
User-Defined Exceptions.
User-defined exceptions allow developers to define custom error conditions that are not automatically handled by the system.
To create a user-defined exception, follow these steps:
Declare the exception in the
DECLAREsection.Raise the exception using the
RAISEstatement.Handle the exception in the
EXCEPTIONblock.
DECLARE
insufficient_funds EXCEPTION; -- Step 1: Declare exception
v_balance NUMBER := 500;
v_withdraw_amount NUMBER := 1000;
BEGIN
IF v_withdraw_amount > v_balance THEN
RAISE insufficient_funds; -- Step 2: Raise exception
END IF;
v_balance := v_balance - v_withdraw_amount;
EXCEPTION
WHEN insufficient_funds THEN
DBMS_OUTPUT.PUT_LINE('Error: Insufficient funds in the account.');
END;
/ Exception Handling in PL/SQL.
PL/SQL handles exceptions using the
EXCEPTIONblock, which consists ofWHENclauses to catch specific exceptions.Syntax.
BEGIN
-- Executable statements
EXCEPTION
WHEN exception_name1 THEN
-- Exception handling code
WHEN exception_name2 THEN
-- Exception handling code
WHEN OTHERS THEN
-- Handle all other exceptions
END;
/ EXAMPLE.
DECLARE
v_result NUMBER;
v_salary NUMBER;
BEGIN
v_result := 10 / 0; -- This will cause a division by zero error
SELECT salary INTO v_salary FROM employees WHERE emp_id = 9999; -- Invalid ID
EXCEPTION
WHEN ZERO_DIVIDE THEN
DBMS_OUTPUT.PUT_LINE('Error: Cannot divide by zero.');
WHEN NO_DATA_FOUND THEN
DBMS_OUTPUT.PUT_LINE('Error: No record found for given employee ID.');
WHEN OTHERS THEN
DBMS_OUTPUT.PUT_LINE('An unexpected error occurred: ' || SQLERRM);
END;
/ Using RAISE_APPLICATION_ERROR
RAISE_APPLICATION_ERRORis a built-in procedure that allows users to define custom error messages along with an error code (-20000to-20999).
EXAMPLE.
DECLARE
v_balance NUMBER := 500;
v_withdraw_amount NUMBER := 1000;
BEGIN
IF v_withdraw_amount > v_balance THEN
RAISE_APPLICATION_ERROR(-20001, 'Insufficient balance in the account');
END IF;
v_balance := v_balance - v_withdraw_amount;
END;
/