DEV Community

Pranav Bakare
Pranav Bakare

Posted on • Edited on

PL/SQL Cursors

Cursors in PL/SQL

In PL/SQL, cursors are used to handle multiple rows returned by queries in a controlled manner. A cursor acts like a pointer to the result set of a SQL query, allowing you to retrieve and process each row one at a time. Cursors come in two types - implicit and explicit depending on the level of control you want to exercise over fetching rows.

.
.
.

Implicit Cursors

Definition: Implicit cursors are automatically created and managed by Oracle whenever an SQL statement (like SELECT INTO, INSERT, UPDATE, or DELETE) is executed. These are used when the SQL statement affects a single row or the query is expected to return exactly one row. Implicit cursors do not require explicit handling or management, and PL/SQL handles the opening, fetching, and closing of the cursor automatically.

Key Points:

  • No need for explicit cursor handling (no need to declare, open, fetch, or close).
  • Automatically created when DML statements are executed.

Example of Implicit Cursor:

DECLARE
    v_employee_name VARCHAR2(100);
BEGIN
-- Implicit cursor is used here 
-- because the SELECT statement returns a single row
    SELECT first_name || ' ' || last_name
    INTO v_employee_name
    FROM employees
    WHERE employee_id = 101;

    DBMS_OUTPUT.PUT_LINE('Employee Name: ' || v_employee_name);
END;
/
Enter fullscreen mode Exit fullscreen mode

Explanation:

  • The SELECT INTO statement automatically creates an implicit cursor.
  • The INTO clause stores the retrieved employee’s name into the variable v_employee_name.
  • Since the query is guaranteed to return only one row (based on the WHERE condition), an implicit cursor is sufficient here.

.
.
.

Explicit Cursors

Definition: Explicit cursors are defined and managed by the developer to handle queries that return multiple rows. With explicit cursors, the programmer has control over opening the cursor, fetching rows, and closing the cursor. These cursors are useful when you need to loop through the result set row by row.

Key Points:

  • You must explicitly declare, open, fetch from, and close the cursor.
  • Useful for queries returning multiple rows.
  • Provides fine control over the fetched data.

Steps for Using Explicit Cursors:

  1. Declare the Cursor: Define the SQL query that the cursor will execute.
  2. Open the Cursor: Execute the query and initialize the result set.
  3. Fetch Rows: Retrieve rows one by one from the result set.
  4. Close the Cursor: Release the memory and resources used by the cursor.

Example of Explicit Cursor:

DECLARE
    -- Declare the cursor for selecting employee details
    CURSOR emp_cursor IS
        SELECT employee_id, first_name, last_name
        FROM employees
        WHERE department_id = 10;

    v_employee_id employees.employee_id%TYPE;
    v_first_name employees.first_name%TYPE;
    v_last_name employees.last_name%TYPE;
BEGIN
    -- Open the cursor to execute the query
    OPEN emp_cursor;

    -- Fetch rows one by one using a loop
    LOOP
        FETCH emp_cursor INTO v_employee_id, v_first_name, v_last_name;

        -- Exit the loop when no more rows are found
        EXIT WHEN emp_cursor%NOTFOUND;

        -- Output employee details for each row fetched
        DBMS_OUTPUT.PUT_LINE('ID: ' || v_employee_id || ', Name: ' || v_first_name || ' ' || v_last_name);
    END LOOP;

    -- Close the cursor to release resources
    CLOSE emp_cursor;
END;
/
Enter fullscreen mode Exit fullscreen mode

Explanation:

Declare: The cursor emp_cursor is declared to fetch employee_id, first_name, and last_name from the employees table where the department_id is 10.

Open: The OPEN statement executes the query and prepares the result set for fetching.

Fetch: The FETCH statement retrieves one row at a time into the variables v_employee_id, v_first_name, and v_last_name.

Loop: The loop continues fetching rows until the EXIT WHEN emp_cursor%NOTFOUND condition is true, meaning no more rows are available.

Close: The CLOSE statement releases the resources associated with the cursor.

.
.
.

Cursor Attributes

Cursor attributes help monitor the status of the cursor during its lifecycle. They provide valuable information about the result set and the current position within it.

Important Cursor Attributes:

1. %FOUND: Returns TRUE if the last FETCH was successful (i.e., if a row was fetched), and FALSE otherwise.

2. %NOTFOUND: Returns TRUE if the last FETCH was unsuccessful (i.e., no more rows to fetch), and FALSE otherwise.

3. %ROWCOUNT: Returns the number of rows fetched so far by the cursor.

4. %ISOPEN: Returns TRUE if the cursor is currently open and FALSE if it is closed.

Example Using Cursor Attributes:

DECLARE
    CURSOR emp_cursor IS
        SELECT employee_id FROM employees WHERE department_id = 10;
    v_employee_id employees.employee_id%TYPE;
BEGIN
    -- Open the cursor
    OPEN emp_cursor;

    LOOP
        -- Fetch each row
        FETCH emp_cursor INTO v_employee_id;

        -- Exit loop if no more rows
        EXIT WHEN emp_cursor%NOTFOUND;

        -- Using %ROWCOUNT attribute to get the number of rows processed
        DBMS_OUTPUT.PUT_LINE('Processed Row: ' || emp_cursor%ROWCOUNT || ' Employee ID: ' || v_employee_id);
    END LOOP;

    -- Close the cursor
    CLOSE emp_cursor;
END;
/

Enter fullscreen mode Exit fullscreen mode

Explanation:

The %ROWCOUNT attribute tracks the number of rows processed, printing the count after each row is fetched.

The loop terminates when emp_cursor%NOTFOUND becomes TRUE, meaning no more rows are available.

.
.
.

Types of Explicit Cursors

In PL/SQL, explicit cursors can be classified into a few specialized types based on their functionality:

1. Parameterized Cursors:

Cursors that accept parameters, allowing you to pass values dynamically into the query.

Example of Parameterized Cursor:

DECLARE
    CURSOR emp_cursor (p_dept_id NUMBER) IS
        SELECT employee_id, first_name, last_name
        FROM employees
        WHERE department_id = p_dept_id;

    v_employee_id employees.employee_id%TYPE;
    v_first_name employees.first_name%TYPE;
    v_last_name employees.last_name%TYPE;
BEGIN
    -- Open the cursor with a specific department ID
    OPEN emp_cursor(10);

    LOOP
        FETCH emp_cursor INTO v_employee_id, v_first_name, v_last_name;
        EXIT WHEN emp_cursor%NOTFOUND;

        DBMS_OUTPUT.PUT_LINE('ID: ' || v_employee_id || ', Name: ' || v_first_name || ' ' || v_last_name);
    END LOOP;

    CLOSE emp_cursor;
END;
/
Enter fullscreen mode Exit fullscreen mode

Explanation:
The cursor emp_cursor is parameterized to accept a p_dept_id value, allowing it to fetch employees based on different department IDs passed during the OPEN statement.

2. FOR Loop Cursor:

A cursor that simplifies fetching by automatically opening, fetching, and closing the cursor.

Example of FOR Loop Cursor:

BEGIN
    FOR emp_rec IN (SELECT employee_id, first_name, last_name FROM employees WHERE department_id = 10) LOOP
        DBMS_OUTPUT.PUT_LINE('ID: ' || emp_rec.employee_id || ', Name: ' || emp_rec.first_name || ' ' || emp_rec.last_name);
    END LOOP;
END;
/
Enter fullscreen mode Exit fullscreen mode

Explanation:
The FOR loop automatically manages the cursor, eliminating the need for OPEN, FETCH, and CLOSE statements. It iterates over each row and processes it.


Key Takeaways:

Implicit Cursors are simple and managed automatically by Oracle, used when queries return a single row.

  • 1. Explicit Cursors provide more control and are ideal for processing multiple rows. Developers manually manage opening, fetching, and closing these cursors.
  • 2. Cursor attributes like %FOUND, %NOTFOUND, %ROWCOUNT, and %ISOPEN help in monitoring the status and managing the flow of cursor operations.
  • 3. Using Parameterized Cursors allows flexibility in querying data with dynamic inputs.
  • 4. A FOR Loop Cursor is a shorthand method that simplifies fetching rows without explicit management.

Mastering these different types of cursors ensures you handle complex query results efficiently and write more robust PL/SQL code.

Top comments (2)

Collapse
 
martinbaun profile image
Martin Baun

Meanwhile I’m 10+ years in with SQL and have never touched cursors, needed this :P

Collapse
 
mrcaption49 profile image
Pranav Bakare

Good to see You like the article... Keep supporting