PLSQL s05 l02
PLSQL s05 l02
All rights
reserved.
Database Programming with
PL/SQL
Using Explicit Cursor Attributes
2 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Objectives
This lesson covers the following objectives:
Define a record structure using the %ROWTYPE attribute
Create PL/SQL code to process the rows of an active set
using record types in cursors
Retrieve information about the state of an explicit cursor
using cursor attributes
Using Explicit Cursor Attributes
3 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Purpose
One of the reasons to use explicit cursors is that they
give you greater programmatic control when handling
your data. This lesson discusses techniques for using
explicit cursors more effectively.
Cursor records enable you to declare a single
variable for all the selected columns in a cursor.
Cursor attributes enable you to retrieve information
about the state of your explicit cursor.
Using Explicit Cursor Attributes
4 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Cursors and Records
The cursor in this example is based on a SELECT
statement that retrieves only two columns of each table
row. What if it retrieved six columns .. or seven, or
eight, or twenty?
Using Explicit Cursor Attributes
DECLARE
v_emp_id employees.employee_id%TYPE;
v_last_name employees.last_name%TYPE;
CURSOR emp_cursor IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = 30;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor
INTO v_emp_id, v_last_name;
...
5 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Cursors and Records (cont.)
This cursor retrieves whole rows of EMPLOYEES.
Messy and long-winded, isnt it?
Using Explicit Cursor Attributes
DECLARE
v_emp_id employees.employee_id%TYPE;
v_first_name employees.first_name%TYPE;
v_last_name employees.last_name%TYPE;
...
v_department_id employees.department_id%TYPE;
CURSOR emp_cursor IS
SELECT * FROM employees
WHERE department_id = 30;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor
INTO v_emp_id, v_first_name, v_last_name ...
v_department_id;
...
6 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Cursors and Records (cont.)
Compare the following snippets of code. What
differences do you see?
Using Explicit Cursor Attributes
DECLARE
v_emp_id ...;
v_first_name ...;
...
v_department_id ...:
CURSOR emp_cursor IS
SELECT * FROM employees
WHERE department_id =30;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor
INTO v_emp_id, v_first_name,
... v_department_id;
...
DECLARE
CURSOR emp_cursor IS
SELECT * FROM employees
WHERE department_id = 30;
v_emp_record
emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor
INTO v_emp_record;
...
7 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Cursors and Records (cont.)
The code on the right uses %ROWTYPE to declare a
record structure based on the cursor. A record is a
composite data type in PL/SQL.
Using Explicit Cursor Attributes
DECLARE
v_emp_id ...;
v_first_name ...;
...
v_department_id ...:
CURSOR emp_cursor IS
SELECT * FROM employees
WHERE department_id = 30;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor
INTO v_emp_id, v_first_name,
... v_department_id;
...
DECLARE
CURSOR emp_cursor IS
SELECT * FROM employees
WHERE department_id = 30;
v_emp_record
emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor
INTO v_emp_record;
...
Variables
Records
8 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Structure of a PL/SQL Record
A record is a composite data type, consisting of a
number of fields each with their own name and data
type.
You reference each field by dot-prefixing its field-name
with the record-name.
%ROWTYPE declares a record with the same fields as
the cursor on which it is based.
Using Explicit Cursor Attributes
Field1 (data type) Field2 (data type) Field3 (data type)
9 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Structure of cursor_name%ROWTYPE
Using Explicit Cursor Attributes
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name, salary FROM employees
WHERE department_id = 30;
v_emp_record emp_cursor%ROWTYPE;
...
v_emp_record.employee_id v_emp_record.last_name v_emp_record.salary
100 King 24000
10 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Cursors and %ROWTYPE
%ROWTYPE is convenient for processing the rows of the
active set because you can simply fetch into the record.
Using Explicit Cursor Attributes
DECLARE
CURSOR emp_cursor IS
SELECT * FROM employees
WHERE department_id = 30;
v_emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_emp_record;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id|| ' - '
||v_emp_record.last_name);
END LOOP;
CLOSE emp_cursor;
END;
11 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Cursors and %ROWTYPE: Another Example
Using Explicit Cursor Attributes
DECLARE
CURSOR emp_dept_cursor IS
SELECT first_name, last_name, department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id;
v_emp_dept_record emp_dept_cursor%ROWTYPE;
BEGIN
OPEN emp_dept_cursor;
LOOP
FETCH emp_dept_cursor INTO v_emp_dept_record;
EXIT WHEN emp_dept_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_dept_record.first_name
||' '||v_emp_dept_record.last_name
||' '||v_emp_dept_record.department_name);
END LOOP;
CLOSE emp_dept_cursor;
END;
12 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Explicit Cursor Attributes
As with implicit cursors, there are several attributes for
obtaining status information about an explicit cursor.
When appended to the cursor variable name, these
attributes return useful information about the execution
of a cursor manipulation statement.
Using Explicit Cursor Attributes
Attribute Type Description
%ISOPEN Boolean Evaluates to TRUE if the cursor is open.
%NOTFOUND Boolean
Evaluates to TRUE if the most recent fetch did not return
a row.
%FOUND Boolean
Evaluates to TRUE if the most recent fetch returned a
row; opposite of %NOTFOUND.
%ROWCOUNT Number Evaluates to the total number of rows FETCHed so far.
13 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
%ISOPEN Attribute
You can fetch rows only when the cursor is open. Use
the %ISOPEN cursor attribute before performing a fetch
to test whether the cursor is open. %ISOPEN returns
the status of the cursor: TRUE if open and FALSE if
not.
Example:
Using Explicit Cursor Attributes
IF NOT emp_cursor%ISOPEN THEN
OPEN emp_cursor;
END IF;
LOOP
FETCH emp_cursor...
14 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
%ROWCOUNT and %NOTFOUND Attributes
Usually the %ROWCOUNT and %NOTFOUND attributes
are used in a loop to determine when to exit the loop.
Use the %ROWCOUNT cursor attribute for the following:
To process an exact number of rows
To count the number of rows fetched so far in a loop
and/or determine when to exit the loop
Using Explicit Cursor Attributes
15 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
%ROWCOUNT and %NOTFOUND Attributes (cont.)
Use the %NOTFOUND cursor attribute for the following:
To determine whether the query found any rows
matching your criteria
To determine when to exit the loop
Using Explicit Cursor Attributes
16 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Example of %ROWCOUNT and %NOTFOUND
This example shows how you can use %ROWCOUNT
and %NOTFOUND attributes for exit conditions in a loop.
Using Explicit Cursor Attributes
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees;
v_emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_emp_record;
EXIT WHEN emp_cursor%ROWCOUNT > 10 OR emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id
||' '|| v_emp_record.last_name);
END LOOP;
CLOSE emp_cursor;
END;
17 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Explicit Cursor Attributes in SQL Statements
You cannot use an explicit cursor attribute directly in an
SQL statement. The following code returns an error:
Using Explicit Cursor Attributes
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, salary FROM employees
ORDER BY SALARY DESC;
v_emp_record emp_cursor%ROWTYPE;
v_count NUMBER;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO v_emp_record;
EXIT WHEN emp_cursor%NOTFOUND;
INSERT INTO top_paid_emps
(employee_id, rank, salary)
VALUES
(v_emp_record.employee_id, emp_cursor%ROWCOUNT,
v_emp_record.salary);
...
18 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Terminology
Key terms used in this lesson included:
%ISOPEN
%NOTFOUND
Record
%ROWCOUNT
%ROWTYPE
Using Explicit Cursor Attributes
19 Copyright 2013, Oracle and/or its affiliates. All rights
reserved.
Summary
In this lesson, you should have learned how to:
Define a record structure using the %ROWTYPE attribute
Create PL/SQL code to process the rows of an active set
using record types in cursors
Retrieve information about the state of an explicit cursor
using cursor attributes
Using Explicit Cursor Attributes