Explicit Cursors |
Introduction
to Oracle SQL & PL/SQL |
Oracle uses
cursors to process all SQL statements. From SQL*Plus, you issue a
command and Oracle takes care of creating a cursor and processing the
command. These types of cursors are called implicit
cursors, because you (the user) cannot not name or control the cursor
directly. In PL/SQL
you also use implicit cursors for DML statements and single select
statements.
Implicit
(static) cursor: commonly refers to the good old SELECT INTO, in which
Oracle implicitly opens, executes and closes the cursor for you,
depositing any selected values of a single row INTO program data
structures.
CREATE
OR REPLACE PROCEDURE show_title (author_in IN magazine.author%TYPE)
IS
l_title
magazine.title%TYPE;
BEGIN
SELECT title INTO
l_title
FROM
magazine
WHERE author =
author_in;
END;
The single select is a simple solution, but insufficient to solve the following problems.
To address these problems you need to use explicit cursors.
Explicit cursors work the same way implicit cursors work, but you control the execution explicitly.
DECLARE |
Examining each statement in turn:
DECLARE |
Oracle allocates memory and processes the query
|
BEGIN |
Oracle binds variables, and executes query identifying the
active set. |
FETCH ename_cursor INTO v_ename; |
Oracle fetches a row from the active set, sets the value of
v_ename, and advances the pointer to the active set. |
FETCH ename_cursor INTO v_ename; |
Oracle fetches a row from the active set (as
above). |
CLOSE ename_cursor; |
Oracle releases memory area. |
Use cursor attributes to determine whether the row was found and what number the row is.
Cursor Attributes |
|
Attribute |
Description |
cur%ISOPEN |
Returns TRUE if cursor is open. |
cur%NOTFOUND |
Returns FALSE if the last FETCH found a row. |
cur%FOUND |
Returns TRUE if the last FETCH found a row.. (Logical inverse of %NOTFOUND). |
cur%ROWCOUNT |
Returns the number of rows modified by the DML statement. |
SQL%BULK_ROWCOUNT |
Returns the number of rows processed for each execution of the bulk DML operation. |
Example using cursor attributes:
DECLARE |
Instead of fetching values into a collection of variables, you could fetch the entire row into a record like so.
DECLARE BEGIN |
You can reference the fields of a record using the syntax record_name.field_name.
In addition to basing a record on a cursor, you can also define records based on tables like so.
DECLARE
CURSOR emp_cursor IS
SELECT *
FROM emp
WHERE deptno=30;
emp_row emp%ROWTYPE; -- This creates a record named EMP_ROW
-- based on the structure of the EMP table
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor
INTO emp_row;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(emp_row.ename||' ['||emp_row.empno
||'] makes '||TO_CHAR(emp_row.sal*12,'$99,990.00'));
END LOOP;
END;
/