More Related Content Similar to PL/SQL CURSORES (20) More from Richard Eliseo Mendoza Gafaro (20) PL/SQL CURSORES2. 2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-1
Introduction to Explicit Cursors
3. 3
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Objectives
This lesson covers the following objectives:
−Distinguish between an implicit and an explicit cursor
−Describe why and when to use an explicit cursor in PL/SQL
code
−List two or more guidelines for declaring and controlling
explicit cursors
−Create PL/SQL code that successfully opens a cursor and
fetches a piece of data into a variable
3
4. 4
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Objectives
Objectives continued:
−Use a simple loop to fetch multiple rows from a cursor
−Create PL/SQL code that successfully closes a cursor after
fetching data into a variable
4
5. 5
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Purpose
•You have learned that a SQL SELECT statement in a
PL/SQL block is successful only if it returns exactly one
row
•What if you need to write a SELECT statement that
returns more than one row?
•For example, you need to produce a report of all
employees?
•To return more than one row, you must declare and
use an explicit cursor
5
6. 6
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Context Areas and Cursors
•The Oracle server allocates a private memory area
called a context area to store the data processed by a
SQL statement
• Every context area (and therefore every SQL
statement) has a cursor associated with it
6
Context Area
Cursor
7. 7
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Context Areas and Cursors
•You can think of a cursor either as a label for the
context area, or as a pointer to the context area
•In fact, a cursor is both of these items
7
Context Area
Cursor
8. A SQL cursor is a private Oracle SQL working area. The implicit cursor is used by the server to test
and parse the SQL statements. Using implicit cursors, we can test the outcome of SQL statements
in PL/SQL.
An implicit cursor is always called “SQL”, and we can access its attributes: SQL%FOUND,
SQL%NOTFOUND, and SQL%ROWCOUNT.
8
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Implicit and Explicit Cursors
There are two types of cursors:
−Implicit cursors: Defined automatically by Oracle for all SQL
DML statements (INSERT, UPDATE, DELETE, and MERGE), and
for SELECT statements that return only one row
−Explicit cursors: Declared by the programmer for queries that
return more than one row
• You can use explicit cursors to name a context area and access its
stored data
8
9. In all situations where the SELECT statement may return more than one row, and in situations
where multiple rows are needed for processing, programmers must declare and use an explicit
cursor.
9
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Limitations of Implicit Cursors
•Programmers must think about the data that is
possible as well as the data that actually exists now
•If there ever is more than one row in the EMPLOYEES
table, the SELECT statement below (without a WHERE
clause) will cause an error
9
DECLARE
v_salary employees.salary%TYPE;
BEGIN
SELECT salary INTO v_salary
FROM employees;
DBMS_OUTPUT.PUT_LINE(' Salary is : '||v_salary);
END;
ORA-01422: exact fetch returns more than requested number of rows
10. 10
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Limitations of Implicit Cursors
To limit the SELECT statement so it returns only one row,
the WHERE clause must be matching on either the
primary key or other unique column. For example:
• SELECT …
• FROM employees
• WHERE employee_id = 101;
• Group functions without a GROUP BY clause also
return exactly one row
•For example:
− SELECT COUNT(*) INTO v_number_of_employees
− FROM employees;
10
11. 11
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Explicit Cursors
•With an explicit cursor, you can retrieve multiple rows
from a database table, have a pointer to each row that
is retrieved, and work on the rows one at a time
•Reasons to use an explicit cursor:
−It is the only way in PL/SQL to retrieve more than one row
from a table
−Each row is fetched by a separate program statement, giving
the programmer more control over the processing of the
rows
11
12. As with variables to be used in the block of code, cursors are defined in the declarative section. To
access the data represented by the cursor definition, you must first OPEN the cursor, then FETCH
the current row from the cursor in order to process the data in that row. When all required data is
processed and/or the cursor is no longer needed, you must CLOSE the cursor.
The meaning and use of the keywords CURSOR, OPEN, FETCH, and CLOSE will be explained and
demonstrated over the next several slides.
12
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Example of an Explicit Cursor
•The following example uses an explicit cursor to display
each row from the departments table
12
DECLARE
CURSOR cur_depts IS
SELECT department_id, department_name FROM departments;
v_department_id departments.department_id%TYPE;
v_department_name departments.department_name%TYPE;
BEGIN
OPEN cur_depts;
LOOP
FETCH cur_depts INTO v_department_id, v_department_name;
EXIT WHEN cur_depts%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_department_id||' '||v_department_name);
END LOOP;
CLOSE cur_depts;
END;
13. 13
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Explicit Cursor Operations
•The set of rows returned by a multiple-row query is
called the active set, and is stored in the context area
•Its size is the number of rows that meet your query
criteria
13
Active set
Table
100 King AD_PRES
101 Kochhar AD_VP
102 De Haan AD_VP
139 Seo ST_CLERK
Explicit Cursor
14. 14
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Explicit Cursor Operations
•Think of the context area (named by the cursor) as a
box, and the active set as the contents of the box
•To get at the data, you must OPEN the box and FETCH
each row from the box one at a time
•When finished, you must CLOSE the box
14
Active set
Table
100 King AD_PRES
101 Kochhar AD_VP
102 De Haan AD_VP
139 Seo ST_CLERK
Explicit Cursor
15. The FETCH statement retrieves the current row and advances the cursor to the next row until the
last row is retrieved or until a specified condition is met.
15
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Controlling Explicit Cursors
15
Fetch each row,
one at a time.
Close the cursor.
Cursor
pointer
Open the cursor.
1
2
3
Cursor
pointer
Cursor
pointer
16. 16
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Steps for Using Explicit Cursors
•You first DECLARE a cursor, and then you use the OPEN,
FETCH, and CLOSE statements to control a cursor.
16
Retrieve the
current row
into
variables.
FETCH
Test for
remaining
rows.
Return to
FETCH if
additional
row found.
Release the
active set.
CLOSE
Define the
cursor.
DECLARE
Fill the
cursor
active set
with data.
OPEN EXIT
17. 17
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Steps for Using Explicit Cursors
•Now that you have a conceptual understanding of
cursors, review the steps to use them:
−1. DECLARE the cursor in the declarative section by naming it
and defining the SQL SELECT statement to be associated with
it
−2. OPEN the cursor
• This will populate the cursor's active set with the results of the SELECT
statement in the cursor's definition
• The OPEN statement also positions the cursor pointer at the first row
17
18. 18
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Steps for Using Explicit Cursors
•Steps to use cursors continued:
−3. FETCH each row from the active set and load the
data into variables
• After each FETCH, the EXIT WHEN checks to see if the FETCH reached
the end of the active set
• If it did, the NOTFOUND attribute is set to TRUE
• If the end of the active set was reached, the LOOP is exited
−4. CLOSE the cursor
• The CLOSE statement releases the active set of rows
• It is now possible to reopen the cursor to establish a fresh active set
using a new OPEN statement
18
19. 19
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Declaring the Cursor
When declaring the cursor:
−Do not include the INTO clause in the cursor declaration
because it appears later in the FETCH statement
−If processing rows in a specific sequence is required, then use
the ORDER BY clause in the query
−The cursor can be any valid SELECT statement, including joins,
subqueries, and so on
−If a cursor declaration references any PL/SQL variables, these
variables must be declared before declaring the cursor
19
20. In the executable section, a single-row SELECT statement must have an INTO clause. However, a
SELECT statement in a cursor declaration cannot have an INTO clause. This is because you are not
retrieving the data into variables yet (that happens in the FETCH statement).
20
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Syntax for Declaring the Cursor
•The active set of a cursor is determined by the SELECT
statement in the cursor declaration
•Syntax:
•In the syntax:
−cursor_name Is a PL/SQL identifier
−select_statement Is a SELECT statement without
an INTO clause
20
CURSOR cursor_name IS
select_statement;
21. 21
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Declaring the Cursor Example 1
•The cur_emps cursor is declared to retrieve the
employee_id and last_name columns of the employees
working in the department with a department_id of 30
•Note that even if there is currently only one employee
in department #30, we should still declare a cursor,
because in the future there may be more than one
employee
21
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees
WHERE department_id = 30;
...
22. 22
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Declaring the Cursor Example 2
•The cur_depts cursor is declared to retrieve all the
details for the departments with the location_id 1700
•You want to fetch and process these rows in ascending
sequence by department_name
22
DECLARE
CURSOR cur_depts IS
SELECT * FROM departments
WHERE location_id = 1700
ORDER BY department_name;
...
23. 23
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Declaring the Cursor Example 3
•A SELECT statement in a cursor declaration can include
joins, group functions, and subqueries
•This example retrieves each department that has at
least two employees, giving the department name and
number of employees
23
DECLARE
CURSOR cur_depts_emps IS
SELECT department_name, COUNT(*) AS how_many
FROM departments d, employees e
WHERE d.department_id = e.department_id
GROUP BY d.department_name
HAVING COUNT(*) > 1;
...
24. 24
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Opening the Cursor
•The OPEN statement executes the query associated
with the cursor, identifies the active set, and positions
the cursor pointer to the first row
•The OPEN statement is included in the executable
section of the PL/SQL block
24
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees
WHERE department_id = 30;
...
BEGIN
OPEN cur_emps;
...
25. 25
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Opening the Cursor
•The OPEN statement performs
the following operations:
−Allocates memory for a context area
(creates the box to hold the data)
−Executes the SELECT statement in
the cursor declaration, returning the
results into the active set (fills the
box with the data)
−Positions the pointer to the first row
in the active set
25
26. 26
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Fetching Data from the Cursor
•The FETCH statement retrieves the rows from the
cursor one at a time
•After each successful fetch, the cursor advances to the
next row in the active set
26
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =10;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO v_empno, v_lname;
DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);
...
END;
27. 27
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Fetching Data from the Cursor
•Two variables, v_empno and v_lname, were declared
to hold the values fetched from the cursor
27
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =10;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO v_empno, v_lname;
DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);
...
END;
28. As you can see on the slide, we can use explicit cursor attributes to test for the outcome of the
FETCH. Here we are using cur_emps%NOTFOUND to exit the LOOP.
28
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Fetching Data from the Cursor
•The previous code successfully fetched the values from
the first row in the cursor into the variables
•If there are other employees in department 50, you
have to use a loop as shown below to access and
process each row
28
29. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Fetching Data from the Cursor
29
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees
WHERE department_id =50;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_empno, v_lname;
EXIT WHEN cur_emps%NOTFOUND; // exit loop when
NOTFOUND is TRUE
DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);
END LOOP; …
END;
29
30. 30
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Guidelines for Fetching Data From the Cursor
•Follow these guidelines when fetching data from the
cursor:
−Include the same number of variables in the INTO clause of
the FETCH statement as columns in the SELECT statement,
and be sure that the data types are compatible
−Match each variable to correspond to the columns position in
the cursor definition
−Use %TYPE to insure data types are
compatible between variable and table
30
31. 31
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Guidelines for Fetching Data From the Cursor
•Follow these guidelines when fetching data from the
cursor:
−Test to see whether the cursor contains rows
−If a fetch acquires no values, then there are no rows to
process (or left to process) in the active set and no error is
recorded
−You can use the %NOTFOUND cursor attribute to test for the
exit condition
31
32. Answer: The SELECT statement in the cursor declaration returns three columns, but the FETCH
statement references only two variables.
32
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Fetching Data From the Cursor Example 1
•What is wrong with this example?
32
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, salary FROM employees
WHERE department_id =30;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
v_sal employees.salary%TYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_empno, v_lname;
EXIT WHEN cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( v_empno ||' '||v_lname);
END LOOP;
…
END;
33. Answer: There needs to be an EXIT WHEN added after the FETCH line. The OPEN statement
populates the active set with exactly one row. The first time through the loop, that row will be
fetched and displayed. The second (and third, and fourth...) times through the loop, no test is
made for the end of the cursor. Therefore, the first row will be displayed over and over again (or
possibly a time-out type error may occur since the result of the code is an infinite loop).
33
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Fetching Data From the Cursor Example 2
•There is only one employee in department 10
•What happens when this example is executed?
33
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees
WHERE department_id =10;
v_empno employees.employee_id%TYPE;
v_lname employees.last_name%TYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_empno, v_lname;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_lname);
END LOOP;
…
END;
34. Once a CURSOR is CLOSEd, the memory is released. But, the data is still in memory and will be
overwritten when a new OPEN statement is executed. So, if the CURSOR is no longer needed, the
memory can be released. A cursor can be reopened only if it is closed.
34
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Closing the Cursor
•The CLOSE statement disables the cursor, releases the
context area, and undefines the active set
•You should close the cursor after completing the
processing of the FETCH statement
34
...
LOOP
FETCH cur_emps INTO v_empno, v_lname;
EXIT WHEN cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_lname);
END LOOP;
CLOSE cur_emps;
END;
35. 35
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Closing the Cursor
•You can reopen the cursor later if required
•Think of CLOSE as closing and emptying the box, so you
can no longer FETCH its contents
35
...
LOOP
FETCH cur_emps INTO v_empno, v_lname;
EXIT WHEN cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_empno || ' ' || v_lname);
END LOOP;
CLOSE cur_emps;
END;
36. 36
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Guidelines for Closing the Cursor
•Follow these guidelines when closing the cursor:
−A cursor can be reopened only if it is closed
−If you attempt to fetch data from a cursor after it has been
closed, then an INVALID_CURSOR exception is raised
−If you later reopen the cursor, the associated SELECT
statement is re-executed to re-populate the context area with
the most recent data from the database
36
37. 37
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Putting It All Together
•Now, when looking at an explicit cursor, you should be
able to identify the cursor-related keywords and
explain what each statement is doing
37
38. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Putting It All Together
38
DECLARE
CURSOR cur_depts IS
SELECT department_id, department_name FROM departments
v_department_id departments.department_id%TYPE;
v_department_name departments.department_name%TYPE;
BEGIN
OPEN cur_depts;
LOOP
FETCH cur_depts INTO v_department_id, v_department_name;
EXIT WHEN cur_depts%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_department_id||' '||v_department_name);
END LOOP;
CLOSE cur_depts;
END;
38
39. • Active set – The set of rows returned by a multiple row query in an explicit cursor operation.
• CLOSE – Disables a cursor, releases the context area, and undefines the active set.
• Context Area – An allocated memory area used to store the data processed by a SQL statement.
• Cursor – A label for a context area or a pointer to the context area.
• Explicit Cursor – Declared by the programmer for queries that return more than one row.
• FETCH – Statement that retrieves the current row and advances the cursor to the next row
either until there are no more rows or until a specified condition is met.
• Implicit Cursor – Defined automatically by Oracle for all SQL DML statements.
• OPEN – Statement that executes the query associated with the cursor, identifies the active set,
and positions the cursor pointer to the first row.
39
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Terminology
Key terms used in this lesson included:
−Active set
−CLOSE
−Context area
−Cursor
−Explicit cursor
−FETCH
−Implicit cursor
−OPEN
39
40. 40
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Summary
In this lesson, you should have learned how to:
−Distinguish between an implicit and an explicit cursor
−Describe why and when to use an explicit cursor in PL/SQL
code
−List two or more guidelines for declaring and controlling
explicit cursors
−Create PL/SQL code that successfully opens a cursor and
fetches a piece of data into a variable
40
41. 41
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-1
Introduction to Explicit Cursors
Summary
In this lesson, you should have learned how to:
−Use a simple loop to fetch multiple rows from a cursor
−Create PL/SQL code that successfully closes a cursor after
fetching data into a variable
41
44. 2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-2
Using Explicit Cursor Attributes
45. 3
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Objectives
•This lesson covers the following objectives:
−Define a record structure for a cursor 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
3
46. 4
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
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
4
47. 5
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
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 ten, or twenty?
5
DECLARE
v_emp_id employees.employee_id%TYPE;
v_last_name employees.last_name%TYPE;
CURSOR cur_emps IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = 30;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_emp_id, v_last_name;
...
48. There are 11 columns in EMPLOYEES, so 11 variables must be declared and populated by the INTO
clause in the FETCH statement. And what if a twelfth column was added to the table later?
6
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Cursors and Records
•This cursor retrieves whole rows of EMPLOYEES
•Imagine the list of declarations with all columns listed
6
49. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Cursors and Records
7
DECLARE
v_emp_id employees.employee_id%TYPE;
v_first_name employees.first_name%TYPE;
v_last_name employees.last_name%TYPE;
v_email employees.email%TYPE;
v_phone_number employees.phone_number%TYPE;
... FIVE MORE SCALAR VARIABLES REQUIRED TO MATCH THE TABLE
v_department_id employees.department_id%TYPE;
CURSOR cur_emps IS
SELECT * FROM employees
WHERE department_id = 30;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_emp_id, v_first_name,
EIGHT MORE HERE ...
v_department_id;
7
50. 8
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Cursors and Records
•Compare the following snippets of code
•What differences do you see?
8
DECLARE
v_emp_id ...;
v_first_name ...;
... (eight other variables)
v_department_id ...:
CURSOR cur_emps IS
SELECT * FROM employees
WHERE department_id = 30;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps
INTO v_emp_id, v_first_name,
... v_department_id;
...
DECLARE
CURSOR cur_emps IS
SELECT * FROM employees
WHERE department_id = 30;
v_emp_record cur_emps%ROWTYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps
INTO v_emp_record;
...
51. The record definition on the right is more efficient to write and to read.
9
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Cursors and Records
•The code on the left uses %ROWTYPE to declare a
record structure based on the cursor
• A record is a composite data type available in PL/SQL
•V_EMP_RECORD will include all of the columns found
in the EMPLOYEES table
9
52. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes 10
Cursors and Records
DECLARE
CURSOR cur_emps IS
SELECT * FROM employees
WHERE department_id = 30;
v_emp_record cur_emps%ROWTYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps
INTO v_emp_record;
...
Record DECLARE
v_emp_id ...;
v_first_name ...;
... (eight other
variables)
v_department_id ...:
CURSOR cur_emps IS
SELECT * FROM employees
WHERE department_id =
30;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps
INTO v_emp_id,
v_first_name,
... v_department_id;
...
Variables
10
53. PL/SQL variables and cursors have attributes, which are properties that let you reference the data
type and structure of an item without repeating its definition. A percent sign (%) serves as the
attribute indicator.
11
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
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
11
Field2 (data type) Field3 (data type)
Field1 (data type)
54. A record is a composite data type, consisting of a number of fields each with their own name and
data type.
The %ROWTYPE attribute provides a record type that represents a row in a table or a cursor. The
record can store an entire row of data selected from the table or fetched from a cursor.
%ROWTYPE is used to declare variables with a composite type that matches the type of an existing
database cursor or table.
12
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Structure of a Cursor Record
•The whole record is accessed with the name of the
record
•To reference an individual field, use the dot notation as
shown above
12
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name, salary FROM employees
WHERE department_id = 30;
v_emp_record cur_emps%ROWTYPE;
...
v_emp_record.employee_id v_emp_record.last_name v_emp_record.salary
100 King 24000
55. Note: The cursor must be declared before the record which references it. We reference the
individual fields in the record as record_name.field_name (look at the PUT_LINE arguments).
A major benefit of defining record types is the code still works even if another column is added to
the underlying table.
13
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Cursors and %ROWTYPE
•%ROWTYPE is convenient for processing the rows of
the active set because you can simply fetch into the
record
13
56. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Cursors and %ROW
14
DECLARE
CURSOR cur_emps IS
SELECT * FROM employees
WHERE department_id = 30;
v_emp_record cur_emps%ROWTYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_emp_record;
EXIT WHEN cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id || ' - '
|| v_emp_record.last_name);
END LOOP;
CLOSE cur_emps;
END;
14
57. Answer: three fields
v_emp_dept_record.first_name
v_emp_dept_record.last_name
v_emp_dept_record.department_name
15
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Cursors and %ROWTYPE: Another Example
•How many fields does v_emp_dept_record contain,
and what are they?
15
DECLARE
CURSOR cur_emps_dept IS
SELECT first_name, last_name, department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id;
v_emp_dept_record cur_emps_dept%ROWTYPE;
BEGIN
OPEN cur_emps_dept;
LOOP
FETCH cur_emps_dept INTO v_emp_dept_record;
EXIT WHEN cur_emps_dept%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 cur_emps_dept;
END;
58. In order to be able to control the loop we need information about the cursor. The same four, built-
in cursor attributes we looked at in an earlier lesson for implicit cursors can also be used when we
are working with explicit cursors.
The %ISOPEN attribute is never true for implicit cursors, as Oracle is doing all the work for us, it
automatically OPENs, FETCHes, and CLOSEs the cursor. %ISOPEN is useful in blocks where we may
OPEN and CLOSE the cursor conditionally. If you try to OPEN an OPEN cursor, you will get an error,
so we may need to test to see if the cursor is OPEN before we try to OPEN it.
The other three are useful attributes that help to identify where the pointer is in relation to the
data in the CURSOR.
16
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
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
16
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.
59. 17
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
%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:
17
IF NOT cur_emps%ISOPEN THEN
OPEN cur_emps;
END IF;
LOOP
FETCH cur_emps...
60. 18
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
%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
18
61. 19
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
%ROWCOUNT and %NOTFOUND Attributes
•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
19
62. In this example, we exit from the loop and close the cursor when one of two conditions is true:
The active set contains 11 rows or less and we have fetched all of them.
The active set contains at least 12 rows, but we want to fetch only the first 11.
20
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Example of %ROWCOUNT and %NOTFOUND
•This example shows how you can use %ROWCOUNT
and %NOTFOUND attributes for exit conditions in a
loop
20
63. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Example of %ROWCOUNT and %NOTFOUND
21
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees;
v_emp_record cur_emps%ROWTYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_emp_record;
EXIT WHEN cur_emps%ROWCOUNT > 10 OR cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id || ' '
|| v_emp_record.last_name);
END LOOP;
CLOSE cur_emps;
END;
21
64. 22
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Explicit Cursor Attributes in SQL Statements
•You cannot use an explicit cursor attribute directly in
an SQL statement
•The following code returns an error:
22
65. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Explicit Cursor Attributes in SQL Statements
23
DECLARE
CURSOR cur_emps IS
SELECT employee_id, salary
FROM employees
ORDER BY SALARY DESC;
v_emp_record cur_emps%ROWTYPE;
v_count NUMBER;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_emp_record;
EXIT WHEN cur_emps%NOTFOUND;
INSERT INTO top_paid_emps (employee_id, rank, salary)
VALUES
(v_emp_record.employee_id, cur_emps%ROWCOUNT,
v_emp_record.salary);
...
23
66. 24
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Explicit Cursor Attributes in SQL Statements
•To avoid the error on the previous slide, we would copy
the cursor attribute value to a variable, then use the
variable in the SQL statement:
24
67. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Explicit Cursor Attributes in SQL Statements
25
DECLARE
CURSOR cur_emps IS ...;
v_emp_record emp_cursor%ROWTYPE;
v_count NUMBER;
v_rowcount NUMBER; -- declare variable to hold
cursor attribute
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_emp_record;
EXIT WHEN cur_emps%NOTFOUND;
v_rowcount := cur_emps%ROWCOUNT; -- "copy" cursor
attribute to variable
INSERT INTO top_paid_emps (employee_id, rank, salary)
VALUES (v_emp_record.employee_id, v_rowcount,
v_emp_record.salary); -- use -variable in SQL statement
...
25
68. %ISOPEN – Returns the status of the cursor.
%NOTFOUND – An attribute used to determine whether a query found any rows matching the
query criteria.
Record – A composite data type in PL/SQL, consisting of a number of fields each with their own
name and data type.
%ROWCOUNT – An attribute that processes an exact number of rows or counts the number of
rows fetched in a loop.
%ROWTYPE – Declares a record with the same fields as the cursor or table on which it is based.
26
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Terminology
•Key terms used in this lesson included:
−%ISOPEN
−%NOTFOUND
−Record
−%ROWCOUNT
−%ROWTYPE
26
69. 27
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-2
Using Explicit Cursor Attributes
Summary
•In this lesson, you should have learned how to:
−Define a record structure for a cursor 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
27
72. 2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-3
Cursor FOR Loops
73. 3
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Objectives
This lesson covers the following objectives:
−List and explain the benefits of using cursor FOR loops
−Create PL/SQL code to declare a cursor and manipulate it in a
FOR loop
−Create PL/SQL code containing a cursor FOR loop using a
subquery
3
74. 4
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Purpose
•You have already learned how to declare and use a
simple explicit cursor, using DECLARE, OPEN, and
FETCH in a loop, testing for %NOTFOUND, and CLOSE
statement
•Wouldn’t it be easier if you could do all this with just
one statement?
•You can do all of this using a cursor FOR loop
4
75. Cursors and Loops were made for one another. The majority of your PL/SQL programs will involve
working on many rows from the same table, so Oracle made that part easy for you by combining
the declaration of a PL/SQL RECORD and the use of a CURSOR in the cursor FOR loop syntax.
5
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
•A cursor FOR loop processes rows in an explicit cursor
•It is a shortcut because the cursor is opened, a row is
fetched once for each iteration in the loop, the loop
exits when the last row is processed, and the cursor is
closed automatically
•The loop itself is terminated automatically at the end
of the iteration when the last row has been fetched
•Syntax:
5
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
76. 6
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
In the syntax:
−record_name Is the name of the implicitly declared
record (as cursor_name%ROWTYPE)
−cursor_name Is a PL/SQL identifier for a previously
declared cursor
6
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
77. 7
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
•You can simplify your coding by using a cursor FOR loop
instead of the OPEN, FETCH, and CLOSE statements
•A cursor FOR loop implicitly declares its loop counter
as a record that represents a row FETCHed from the
database
• A cursor FOR loop:
−OPENs a cursor
− Repeatedly FETCHes rows of values from the active set into
fields in the record
− CLOSEs the cursor when all rows have been processed
7
78. 8
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
•Note: v_emp_record is the record that is implicitly
declared
•You can access the fetched data with this implicit
record as shown below
8
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees
WHERE department_id = 50;
BEGIN
FOR v_emp_record IN cur_emps LOOP
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id || ' '
|| v_emp_record.last_name);
END LOOP;
END;
79. 9
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
•No variables are declared to hold the fetched data and
no INTO clause is required
•OPEN and CLOSE statements are not required, they
happen automatically in this syntax
9
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees
WHERE department_id = 50;
BEGIN
FOR v_emp_record IN cur_emps LOOP
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id || ' '
|| v_emp_record.last_name);
END LOOP;
END;
80. The cursor FOR loop greatly simplifies the code writing and can make maintenance easier.
Although there are fewer lines of code, using a cursor FOR loop will NOT improve performance.
The OPEN, FETCH ... INTO, EXIT WHEN ...%NOTFOUND, and CLOSE are still happening, they just
happen automatically when combining a cursor with a FOR loop.
10
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
•Compare the cursor FOR loop (on the left) with the
cursor code you learned in the previous lesson
•The two forms of the code are logically identical to
each other and produce exactly the same results
10
81. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
11
DECLARE
CURSOR cur_emps IS
SELECT employee_id,
last_name
FROM employees
WHERE department_id =
50;
BEGIN
FOR v_emp_rec IN cur_emps
LOOP
DBMS_OUTPUT.PUT_LINE(…);
END LOOP;
END;
DECLARE
CURSOR cur_emps IS
SELECT employee_id,
last_name
FROM employees
WHERE department_id =
50;
v_emp_rec
cur_emps%ROWTYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO
v_emp_rec;
EXIT WHEN
cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(…);
END LOOP;
CLOSE cur_emps;
END;
11
82. 12
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
•There is no need to declare the variable v_emp_rec in
the declarative section. The syntax "FOR v_emp_rec IN
…" implicitly defines v_emp_rec
•The scope of the implicit record is restricted to the
loop, so you cannot reference the fetched data outside
the loop
•Within the loop, you can access fetched data using
record_name.column_name
(ex. v_emp_rec.employee_id)
12
83. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops
13
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = 50;
BEGIN
FOR v_emp_rec IN cur_emps LOOP
DBMS_OUTPUT.PUT_LINE(…);
END LOOP;
END;
13
84. Answer: two fields, because the cursor whose %ROWTYPE it is based on SELECTs two table
columns.
14
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops: A Second Example
•v_dept_record has been implicitly declared as
cur_depts%ROWTYPE
•How many fields does it contain?
14
DECLARE
CURSOR cur_depts IS
SELECT department_id, department_name
FROM departments
ORDER BY department_id;
BEGIN
FOR v_dept_record IN cur_depts LOOP
DBMS_OUTPUT.PUT_LINE(v_dept_record.department_id || ' '
|| v_dept_record.department_name);
END LOOP;
END;
85. 15
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Guidelines for Cursor FOR Loops
Guidelines:
−Do not declare the record that controls the loop because it is
declared implicitly
−The scope of the implicit record is restricted to the loop, so
you cannot reference the record outside the loop
−You can access fetched data using
record_name.column_name
15
86. 16
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Testing Cursor Attributes
• You can still test cursor attributes, such as %ROWCOUNT
• This example exits from the loop after five rows have
been fetched and processed
• The cursor is still closed automatically
16
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name
FROM employees;
BEGIN
FOR v_emp_record IN cur_emps LOOP
EXIT WHEN cur_emps%ROWCOUNT > 5;
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id || ' ' ||
v_emp_record.last_name);
END LOOP;
END;
87. 17
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops Using Subqueries
•You can go one step further. You don’t have to declare
the cursor at all!
•Instead, you can specify the SELECT on which the
cursor is based directly in the FOR loop
•The advantage of this is the cursor definition is
contained in a single FOR … statement
•In complex code with lots of cursors, this simplification
makes code maintenance easier and quicker
•The downside is you can't reference cursor attributes
17
88. The downside to this simplification is you cannot reference explicit cursor attributes such as
%ROWCOUNT and %NOTFOUND because the cursor does not have an explicit name (there is no
cur_emps or cur_depts).
18
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops Using Subqueries: Example
•The SELECT clause in the FOR statement is technically a
subquery, so you must enclose it in parentheses
18
BEGIN
FOR v_emp_record IN (SELECT employee_id, last_name
FROM employees WHERE department_id = 50)
LOOP
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id || ' '
|| v_emp_record.last_name);
END LOOP;
END;
89. 19
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Cursor FOR Loops Using Subqueries
•Again, compare these two forms of code
•They are logically identical, but which one would you
rather write – especially if you hate typing!
19
BEGIN
FOR v_dept_rec IN (SELECT *
FROM departments) LOOP
DBMS_OUTPUT.PUT_LINE(…);
END LOOP;
END;
DECLARE
CURSOR cur_depts IS
SELECT * FROM departments;
v_dept_rec
cur_depts%ROWTYPE;
BEGIN
OPEN cur_depts;
LOOP
FETCH cur_depts INTO
v_dept_rec;
EXIT WHEN
cur_depts%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(…);
END LOOP;
CLOSE cur_depts;
END;
90. • Cursor FOR loop – Automates standard cursor-handling operations such as OPEN, FETCH,
%NOTFOUND, and CLOSE, so that they do not need to be coded explicitly
20
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Terminology
Key terms used in this lesson included:
−Cursor FOR loop
20
91. 21
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-3
Cursor FOR Loops
Summary
In this lesson, you should have learned how to:
−List and explain the benefits of using cursor FOR loops
−Create PL/SQL code to declare a cursor and manipulate it in a
FOR loop
−Create PL/SQL code containing a cursor FOR loop using a
subquery
21
94. 2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-4
Cursors with Parameters
95. 3
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Objectives
•This lesson covers the following objectives:
−List the benefits of using parameters with cursors
−Create PL/SQL code to declare and use a cursor with a
parameter
3
96. 4
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Purpose
•Consider a program which declares a cursor to fetch
and process all the employees in a given department,
and the department is chosen by the user at runtime
•How would we declare the cursor?
•We don't know the department id when we write the
code, but this won't work
4
DECLARE
CURSOR cur_emps IS
SELECT * FROM employees
WHERE department_id = ???;
97. 5
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Purpose
•There are several departments
•Do we need to declare several cursors, one for each
department, each with a different value in the WHERE
clause?
•No - we can declare just one cursor to handle all
departments by using parameters
5
98. 6
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursors with Parameters
•A parameter is a variable whose name is used in a
cursor declaration
•When the cursor is opened, the parameter value is
passed to the Oracle server, which uses it to decide
which rows to retrieve into the active set of the cursor
6
99. 7
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursors with Parameters
•This means that you can open and close an explicit
cursor several times in a block, or in different
executions of the same block, returning a different
active set on each occasion
•Consider an example where you pass a location_id to a
cursor and it returns the names of the departments at
that location
•The next slide shows how
7
100. In a production environment, the location_id would not be hard-coded in the OPEN statement,
but would be "entered" by the user in the interface to the database.
8
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursors with Parameters: Example
8
DECLARE
CURSOR cur_country (p_region_id NUMBER) IS
SELECT country_id, country_name
FROM countries
WHERE region_id = p_region_id;
v_country_record cur_country%ROWTYPE;
BEGIN
OPEN cur_country (5);
LOOP
FETCH cur_country INTO v_country_record;
EXIT WHEN cur_country%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_country_record.country_id || ' '
|| v_country_record.country_name);
END LOOP;
CLOSE cur_country;
END;
Change to whichever
region is required.
101. We specify the datatype of the cursor parameter, but not the size. For example: VARCHAR2, not
VARCHAR2(20).
When the cursor is opened, the parameter value is passed to the Oracle server, which uses it to
decide which rows to retrieve into the active set of the cursor. This means that you can open and
close an explicit cursor several times in a block, or in different executions of the same block,
returning a different active set on each occasion.
9
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Defining Cursors with Parameters Syntax
•Each parameter named in the cursor declaration must
have a corresponding value in the OPEN statement
•Parameter data types are the same as those for scalar
variables, but you do not give them sizes
•The parameter names are used in the WHERE clause of
the cursor SELECT statement
9
CURSOR cursor_name
[(parameter_name datatype, ...)]
IS
select_statement;
102. 10
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Defining Cursors with Parameters Syntax
•In the syntax:
−cursor_name Is a PL/SQL identifier for the declared cursor
−parameter_name Is the name of a parameter
−datatype Is the scalar data type of the parameter
−select_statement Is a SELECT statement without the INTO
clause
10
CURSOR cursor_name
[(parameter_name datatype, ...)]
IS
select_statement;
103. 11
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Opening Cursors with Parameters
•The following is the syntax for opening a cursor with
parameters:
11
OPEN cursor_name(parameter_value1, parameter_value2, ...);
104. 12
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursors with Parameters
•You pass parameter values to a cursor when the cursor
is opened
•Therefore you can open a single explicit cursor several
times and fetch a different active set each time
•In the following example, a cursor is opened several
times
12
105. Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursors with Parameters
13
DECLARE
CURSOR cur_countries (p_region_id NUMBER) IS
SELECT country_id, country_name FROM countries
WHERE region_id = p_region_id;
v_country_record c_countries%ROWTYPE;
BEGIN
OPEN cur_countries (5);
...
CLOSE cur_countries;
OPEN cur_countries (145);
...
Open the cursor again and
return a different active set.
13
106. The purpose of this code is to fetch and display all employees in the department with the highest
department_id.
Note that the maximum department_id is stored in the v_deptid variable and is then passed into
the empcur cursor.
Note also that the SELECT MAX(department_id) …. will always return exactly one row, so an
explicit cursor is not needed for this.
14
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Another Example of a Cursor with a Parameter
14
DECLARE
v_deptid employees.department_id%TYPE;
CURSOR cur_emps (p_deptid NUMBER) IS
SELECT employee_id, salary
FROM employees
WHERE department_id = p_deptid;
v_emp_rec cur_emps%ROWTYPE;
BEGIN
SELECT MAX(department_id) INTO v_deptid
FROM employees;
OPEN cur_emps(v_deptid);
LOOP
FETCH cur_emps INTO v_emp_rec;
EXIT WHEN cur_emps%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emp_rec.employee_id || ' '
|| v_emp_rec.salary);
END LOOP;
CLOSE cur_emps;
END;
107. 15
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursor FOR Loops wıth a Parameter
•We can use a cursor FOR loop if needed:
−Parameters are placed inside parentheses following the
CURSOR
−FOR…END LOOP statements let you execute a sequence of
statements multiple times
−The CURSOR will repeatedly use new value(s) that are passed
into the parameter
15
DECLARE
CURSOR cur_emps (p_deptno NUMBER) IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = p_deptno;
BEGIN
FOR v_emp_record IN cur_emps(10) LOOP
...
END LOOP;
END;
108. 16
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursors with Multiple Parameters: Example 1
•In the following example, a cursor is declared and is
called with two parameters:
16
DECLARE
CURSOR cur_countries (p_region_id NUMBER, p_population
NUMBER) IS
SELECT country_id, country_name, population
FROM countries
WHERE region_id = p_region_id
OR population > p_population;
BEGIN
FOR v_country_record IN cur_countries(145,10000000) LOOP
DBMS_OUTPUT.PUT_LINE(v_country_record.country_id ||' '
|| v_country_record. country_name||'
'
|| v_country_record.population);
END LOOP;
END;
109. 17
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Cursors with Multiple Parameters: Example 2
•This cursor fetches all IT Programmers who earn more
than $10000
17
DECLARE
CURSOR cur_emps (p_job VARCHAR2, p_salary NUMBER) IS
SELECT employee_id, last_name
FROM employees
WHERE job_id = p_job
AND salary > p_salary;
BEGIN
FOR v_emp_record IN cur_emps('IT_PROG', 10000) LOOP
DBMS_OUTPUT.PUT_LINE(v_emp_record.employee_id ||' '
|| v_emp_record.last_name);
END LOOP;
END;
110. 18
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-4
Cursors with Parameters
Summary
•In this lesson, you should have learned how to:
−List the benefits of using parameters with cursors
−Create PL/SQL code to declare and use a cursor with a
parameter
18
113. 2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-5
Using Cursors for Update
114. If using the online/hosted Application Express at iAcademy, statements are automatically
committed upon completion (unlike a typical production database where a deliberate COMMIT
statement must be issued to actually modify data stored in the database). Therefore, all your DML
statements will be committed upon completion (thereby releasing all locks held), and you will not
be able to demonstrate locking and lock waits.
3
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
Objectives
•This lesson covers the following objectives:
−Create PL/SQL code to lock rows before an update using the
appropriate clause
−Explain the effect of using NOWAIT in an update cursor
declaration
−Create PL/SQL code to use the current row of the cursor in an
UPDATE or DELETE statement
3
115. 4
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
Purpose
• If multiple users are connected to the database at the same
time, the possibility exists that another user updated the
rows of a particular table after you opened your cursor and
fetched the rows
• We can lock rows as we open the cursor in order to prevent
other users from updating them – this is important
especially if we are going to do updates ourselves
• An open cursor provides a read-consistent view of the data
fetched by the cursor
• This means that any updates made by other users since the
cursor was opened will not be seen when we fetch the
rows, even if the updates were committed
• Our session would have to close and re-open the cursor in
order to see the committed updates
4
116. 5
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
Declaring a Cursor with the FOR UPDATE Syntax
•When we declare a cursor FOR UPDATE, each row is
locked as we open the cursor
•This prevents other users from modifying the rows
while our cursor is open
•It also allows us to modify the rows ourselves using a …
WHERE CURRENT OF … clause
•This does not prevent other users from reading the
rows
5
CURSOR cursor_name IS
SELECT ... FROM ...
FOR UPDATE [OF column_reference][NOWAIT | WAIT n];
117. 6
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
Declaring a Cursor with the FOR UPDATE Clause
•column_reference is a column in the table whose rows
we need to lock
•If the rows have already been locked by another
session:
−NOWAIT returns an Oracle server error immediately
−WAIT n waits for n seconds, and returns an Oracle server
error if the other session is still locking the rows at the end of
that time
6
CURSOR cursor_name IS
SELECT ... FROM ...
FOR UPDATE [OF column_reference][NOWAIT | WAIT n];
118. 7
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
NOWAIT Keyword in the FOR UPDATE Clause Example
•The optional NOWAIT keyword tells the Oracle server
not to wait if any of the requested rows have already
been locked by another user
•Control is immediately returned to your program so
that it can do other work before trying again to acquire
the lock
•If you omit the NOWAIT keyword, then the Oracle
server waits indefinitely until the rows are available
7
DECLARE
CURSOR cur_emps IS
SELECT employee_id, last_name FROM employees
WHERE department_id = 80 FOR UPDATE NOWAIT;
...
119. It may help to think of a lock as being like a red traffic light. If another session has already locked
the rows, the traffic light is red. Using the default, our session is an infinitely patient driver who
will wait indefinitely until the traffic light turns green (i.e. the locks are released). If we use
NOWAIT, we have no patience at all; we see the red light and immediately back off.
8
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
NOWAIT Keyword in the FOR UPDATE Clause
•If the rows are already locked by another session and
you have specified NOWAIT, then opening the cursor
will result in an error
•You can try to open the cursor later
•You can use WAIT n instead of NOWAIT and specify the
number of seconds to wait and check whether the
rows are unlocked
•If the rows are still locked after n seconds, then an
error is returned
8
120. If we don’t specify a column-name, then rows of both tables are locked. This causes unnecessary
extra locking when (in this example) we want to lock only the EMPLOYEES rows, not the
DEPARTMENTS rows.
It doesn’t matter which column-name we use. Individual columns are never locked, only whole
rows.
9
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
FOR UPDATE OF column-name Example
•If the cursor is based on a join of two tables, we may
want to lock the rows of one table but not the other
•To do this, we specify any column of the table we want
to lock
9
DECLARE
CURSOR emp_cursor IS
SELECT e.employee_id, d.department_name
FROM employees e, departments d
WHERE e.department_id = d.department_id
AND department_id = 80 FOR UPDATE OF salary;
...
121. 10
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
WHERE CURRENT OF Clause Syntax
•The WHERE CURRENT OF clause is used in conjunction
with the FOR UPDATE clause to refer to the current row
(the most recently FETCHed row) in an explicit cursor
•The WHERE CURRENT OF clause is used in the UPDATE
or DELETE statement, whereas the FOR UPDATE clause
is specified in the cursor declaration
•cursor_name Is the name of a declared cursor (The
cursor must have been declared with the FOR UPDATE
clause)
10
WHERE CURRENT OF cursor-name;
122. 11
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
WHERE CURRENT OF Clause
•You can use WHERE CURRENT OF for updating or
deleting the current row from the corresponding
database table
•This enables you to apply updates and deletes to the
row currently being addressed, without the need to
use a WHERE clause
•You must include the FOR UPDATE clause in the cursor
query so that the rows are locked on OPEN
11
WHERE CURRENT OF cursor-name;
123. 12
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
WHERE CURRENT OF Clause Example
•Use cursors to update or delete the current row
•Include the FOR UPDATE clause in the cursor query to
lock the rows first
•Use the WHERE CURRENT OF clause to reference the
current row from an explicit cursor
12
UPDATE employees
SET salary = ...
WHERE CURRENT OF cur_emps;
124. 13
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
NOWAIT, FOR UPDATE, and WHERE CURRENT OF
Clause
•In this example, we don’t need a column-reference in
the FOR UPDATE clause because the cursor is not
based on a join
13
DECLARE
CURSOR cur_emps IS
SELECT employee_id, salary FROM my_employees
WHERE salary <= 20000 FOR UPDATE NOWAIT;
v_emp_rec cur_emps%ROWTYPE;
BEGIN
OPEN cur_emps;
LOOP
FETCH cur_emps INTO v_emp_rec;
EXIT WHEN cur_emps%NOTFOUND;
UPDATE my_employees
SET salary = v_emp_rec.salary*1.1
WHERE CURRENT OF cur_emps;
END LOOP;
CLOSE cur_emps;
END;
125. 14
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
FOR UPDATE Second Example
•FOR UPDATE OF salary locks only the MY_EMPLOYEES
rows, not the MY_DEPARTMENTS rows
•Note that we update the table-name, not the cursor-
name!
14
DECLARE
CURSOR cur_eds IS
SELECT employee_id, salary, department_name
FROM my_employees e, my_departments d
WHERE e.department_id = d.department_id
FOR UPDATE OF salary NOWAIT;
BEGIN
FOR v_eds_rec IN cur_eds LOOP
UPDATE my_employees
SET salary = v_eds_rec.salary * 1.1
WHERE CURRENT OF cur_eds;
END LOOP;
END;
126. • FOR UPDATE – Declares that each row is locked as it is being fetched so other users can not
modify the rows while the cursor is open.
• NOWAIT – A keyword used to tell the Oracle server not to wait if the requested rows have
already been locked by another user.
15
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
Terminology
•Key terms used in this lesson included:
−FOR UPDATE
−NOWAIT
15
127. 16
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-5
Using Cursors for Update
Summary
•In this lesson, you should have learned how to:
−Create PL/SQL code to lock rows before an update using the
appropriate clause
−Explain the effect of using NOWAIT in an update cursor
declaration
−Create PL/SQL code to use the current row of the cursor in an
UPDATE or DELETE statement
16
130. 2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-6
Using Multiple Cursors
131. 3
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Objectives
•This lesson covers the following objectives:
−Explain the need for using multiple cursors to produce multi-
level reports
−Create PL/SQL code to declare and manipulate multiple
cursors within nested loops
−Create PL/SQL code to declare and manipulate multiple
cursors using parameters
3
132. 4
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Purpose
•In real-life programs you often need to declare and use
two or more cursors in the same PL/SQL block
•Often these cursors are related to each other by
parameters
•One common example is the need for multi-level
reports in which each level of the report uses rows
from a different cursor
•This lesson does not introduce new concepts or syntax
•It shows more powerful uses for the concepts and
syntax that you already know
4
133. 5
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
A Sample Problem Statement
•You need to produce a report that lists each
department as a sub-heading, immediately followed by
a listing of the employees in that department, followed
by the next department, and so on
•You need two cursors, one for each of the two tables
•The cursor based on EMPLOYEES is opened several
times, once for each department
5
134. Answer: Because we will OPEN C_EMP several times (once for each department) and it must fetch
a different set of rows each time.
6
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Problem Solution: Step 1
•Declare two cursors, one for each table, plus
associated record structures
•Why is cursor cur_emp declared with a parameter?
6
DECLARE
CURSOR cur_dept IS
SELECT department_id, department_name
FROM departments
ORDER BY department_name;
CURSOR cur_emp (p_deptid NUMBER) IS
SELECT first_name, last_name
FROM employees
WHERE department_id = p_deptid
ORDER BY last_name;
v_deptrec cur_dept%ROWTYPE;
v_emprec cur_emp%ROWTYPE;
135. 7
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Problem Solution: Step 2
•Open the cur_dept cursor and fetch and display the
DEPARTMENTS rows in the usual way
7
DECLARE
CURSOR cur_dept IS .....;
CURSOR cur_emp (p_deptid NUMBER) IS .....;
v_deptrec cur_dept%ROWTYPE;
v_emprec cur_emp%ROWTYPE;
BEGIN
OPEN cur_dept;
LOOP
FETCH cur_dept INTO v_deptrec;
EXIT WHEN cur_dept%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_deptrec.department_name);
END LOOP;
CLOSE cur_dept;
END;
136. 8
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Problem Solution: Step 3
•After each DEPARTMENTS row has been fetched and
displayed, you need to fetch and display the
EMPLOYEES in that department
•To do this, you open the EMPLOYEES cursor, fetch and
display its rows in a nested loop, and close the cursor
•Then, you do the same for the next DEPARTMENTS row
•And so on
•The next slide shows the code for this
8
137. The inner CUR_EMP loop executes once for each row fetched by the CUR_DEPT cursor and fetches
a different subset of EMPLOYEES each time due to the parameter p_deptid.
9
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Problem Solution
9
DECLARE
CURSOR cur_dept IS .....;
CURSOR cur_emp (p_deptid NUMBER) IS .....;
v_deptrec cur_dept%ROWTYPE;
v_emprec cur_emp%ROWTYPE;
BEGIN
OPEN cur_dept;
LOOP
FETCH cur_dept INTO v_deptrec;
EXIT WHEN cur_dept%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_deptrec.department_name);
OPEN cur_emp (v_deptrec.department_id);
LOOP
FETCH cur_emp INTO v_emprec;
EXIT WHEN cur_emp%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_emprec.last_name || ' ' ||
v_emprec.first_name);
END LOOP;
CLOSE cur_emp;
END LOOP;
CLOSE cur_dept;
END;
138. In many situations involving multilevel reports, the tables will usually be related to each other by a
foreign key.
10
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
A Second Example
•You need to produce a report that lists each location in
which your departments are situated, followed by the
departments in that location
•Again, you need two cursors, one for each of the two
tables
•The cursor based on DEPARTMENTS will be opened
several times, once for each location
•The next slide shows the code needed to produce this
report
10
139. The inner CUR_DEPT loop executes once for each row fetched by the CUR_LOC cursor and, due to
the parameter p_locid, fetches a different subset of DEPARTMENTS each time.
11
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
A Second Example
11
DECLARE
CURSOR cur_loc IS SELECT * FROM locations;
CURSOR cur_dept (p_locid NUMBER) IS
SELECT * FROM departments WHERE location_id = p_locid;
v_locrec cur_loc%ROWTYPE;
v_deptrec cur_dept%ROWTYPE;
BEGIN
OPEN cur_loc;
LOOP
FETCH cur_loc INTO v_locrec;
EXIT WHEN cur_loc%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_locrec.city);
OPEN cur_dept (v_locrec.location_id);
LOOP
FETCH cur_dept INTO v_deptrec;
EXIT WHEN cur_dept%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_deptrec.department_name);
END LOOP;
CLOSE cur_dept;
END LOOP;
CLOSE cur_loc;
END;
140. This code is functionally identical to that in the previous slide, but is more compact and easier to
maintain.
12
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Using FOR Loops with Multiple Cursors
•You can use FOR loops (and other cursor techniques,
such as FOR UPDATE) with multiple cursors, just as you
can with single cursors
12
DECLARE
CURSOR cur_loc IS SELECT * FROM locations;
CURSOR cur_dept (p_locid NUMBER) IS
SELECT * FROM departments WHERE location_id = p_locid;
BEGIN
FOR v_locrec IN cur_loc
LOOP
DBMS_OUTPUT.PUT_LINE(v_locrec.city);
FOR v_deptrec IN cur_dept (v_locrec.location_id)
LOOP
DBMS_OUTPUT.PUT_LINE(v_deptrec.department_name);
END LOOP;
END LOOP;
END;
141. Answer: employees in department 1700 who currently earn less than 10000.
13
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
A Final Example
•Which employees will receive a salary increase by
running the code below?
13
DECLARE
CURSOR cur_dept IS SELECT * FROM my_departments;
CURSOR cur_emp (p_dept_id NUMBER) IS
SELECT * FROM my_employees WHERE department_id = p_dept_id
FOR UPDATE NOWAIT;
BEGIN
FOR v_deptrec IN cur_dept LOOP
DBMS_OUTPUT.PUT_LINE(v_deptrec.department_name);
FOR v_emprec IN cur_emp (v_deptrec.department_id) LOOP
DBMS_OUTPUT.PUT_LINE(v_emprec.last_name);
IF v_deptrec.location_id = 1700 AND v_emprec.salary < 10000
THEN UPDATE my_employees
SET salary = salary * 1.1
WHERE CURRENT OF cur_emp;
END IF;
END LOOP;
END LOOP;
END;
142. 14
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
PLSQL 5-6
Using Multiple Cursors
Summary
•In this lesson, you should have learned how to:
−Explain the need for using multiple cursors to produce multi-
level reports
−Create PL/SQL code to declare and manipulate multiple
cursors within nested loops
−Create PL/SQL code to declare and manipulate multiple
cursors using parameters
14