SlideShare a Scribd company logo
1 of 143
Download to read offline
1
2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-1
Introduction to Explicit Cursors
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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;
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
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
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
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
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;
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;
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
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
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
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
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
• 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
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
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
42
1
2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-2
Using Explicit Cursor Attributes
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
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
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;
...
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
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
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;
...
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
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
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)
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
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
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
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;
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.
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...
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
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
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
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
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
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
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
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
%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
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
28
1
2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-3
Cursor FOR Loops
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
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
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;
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;
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
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;
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;
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
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
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
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
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;
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
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;
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
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;
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;
• 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
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
22
1
2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-4
Cursors with Parameters
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
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 = ???;
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
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
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
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.
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;
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;
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, ...);
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
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
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;
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;
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;
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;
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
19
1
2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-5
Using Cursors for Update
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
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
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];
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];
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;
...
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
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;
...
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;
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;
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;
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;
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;
• 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
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
17
1
2
Copyright © 2020, Oracle and/or its affiliates. All rights reserved.
Database Programming with
PL/SQL
5-6
Using Multiple Cursors
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
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
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
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;
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;
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
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;
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
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;
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;
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;
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
15

More Related Content

What's hot

10g plsql slide
10g plsql slide10g plsql slide
10g plsql slide
Tanu_Manu
 

What's hot (18)

Lesson01 学会使用基本的SQL语句
Lesson01 学会使用基本的SQL语句Lesson01 学会使用基本的SQL语句
Lesson01 学会使用基本的SQL语句
 
Oracle sql & plsql
Oracle sql & plsqlOracle sql & plsql
Oracle sql & plsql
 
Les01
Les01Les01
Les01
 
DBMS 2011
DBMS 2011DBMS 2011
DBMS 2011
 
10g plsql slide
10g plsql slide10g plsql slide
10g plsql slide
 
4. plsql
4. plsql4. plsql
4. plsql
 
05 Creating Stored Procedures
05 Creating Stored Procedures05 Creating Stored Procedures
05 Creating Stored Procedures
 
plsql Les09
 plsql Les09 plsql Les09
plsql Les09
 
Introduction to PL/SQL
Introduction to PL/SQLIntroduction to PL/SQL
Introduction to PL/SQL
 
Open Gurukul Language PL/SQL
Open Gurukul Language PL/SQLOpen Gurukul Language PL/SQL
Open Gurukul Language PL/SQL
 
SQL- Introduction to PL/SQL
SQL- Introduction to  PL/SQLSQL- Introduction to  PL/SQL
SQL- Introduction to PL/SQL
 
Writing Basic SQL SELECT Statements
Writing Basic SQL SELECT StatementsWriting Basic SQL SELECT Statements
Writing Basic SQL SELECT Statements
 
Oracle SQL, PL/SQL best practices
Oracle SQL, PL/SQL best practicesOracle SQL, PL/SQL best practices
Oracle SQL, PL/SQL best practices
 
Displaying Data from Multiple Tables - Oracle Data Base
Displaying Data from Multiple Tables - Oracle Data BaseDisplaying Data from Multiple Tables - Oracle Data Base
Displaying Data from Multiple Tables - Oracle Data Base
 
Aggregating Data Using Group Functions
Aggregating Data Using Group FunctionsAggregating Data Using Group Functions
Aggregating Data Using Group Functions
 
Packages in PL/SQL
Packages in PL/SQLPackages in PL/SQL
Packages in PL/SQL
 
Forall & bulk binds
Forall & bulk bindsForall & bulk binds
Forall & bulk binds
 
122 sql for-beginners
122 sql for-beginners122 sql for-beginners
122 sql for-beginners
 

Similar to PL/SQL CURSORES

3963066 pl-sql-notes-only
3963066 pl-sql-notes-only3963066 pl-sql-notes-only
3963066 pl-sql-notes-only
Ashwin Kumar
 
plsql tutorialhub....
plsql tutorialhub....plsql tutorialhub....
plsql tutorialhub....
Abhiram Vijay
 
L9 l10 server side programming
L9 l10  server side programmingL9 l10  server side programming
L9 l10 server side programming
Rushdi Shams
 
Advanced_SQL_ISASasASasaASnjection (1).ppt
Advanced_SQL_ISASasASasaASnjection (1).pptAdvanced_SQL_ISASasASasaASnjection (1).ppt
Advanced_SQL_ISASasASasaASnjection (1).ppt
ssuserde23af
 

Similar to PL/SQL CURSORES (20)

3963066 pl-sql-notes-only
3963066 pl-sql-notes-only3963066 pl-sql-notes-only
3963066 pl-sql-notes-only
 
Cursors.ppt
Cursors.pptCursors.ppt
Cursors.ppt
 
PLSQL (1).ppt
PLSQL (1).pptPLSQL (1).ppt
PLSQL (1).ppt
 
Cursores explicitos
Cursores explicitosCursores explicitos
Cursores explicitos
 
Cursors, triggers, procedures
Cursors, triggers, proceduresCursors, triggers, procedures
Cursors, triggers, procedures
 
4 cursors
4 cursors4 cursors
4 cursors
 
Pl sql-ch1
Pl sql-ch1Pl sql-ch1
Pl sql-ch1
 
plsql tutorialhub....
plsql tutorialhub....plsql tutorialhub....
plsql tutorialhub....
 
Cursors
CursorsCursors
Cursors
 
Turbocharge SQL Performance in PL/SQL with Bulk Processing
Turbocharge SQL Performance in PL/SQL with Bulk ProcessingTurbocharge SQL Performance in PL/SQL with Bulk Processing
Turbocharge SQL Performance in PL/SQL with Bulk Processing
 
PL/SQL - CURSORS
PL/SQL - CURSORSPL/SQL - CURSORS
PL/SQL - CURSORS
 
Oracle PL/SQL online training | PL/SQL online Training
Oracle PL/SQL online training | PL/SQL online TrainingOracle PL/SQL online training | PL/SQL online Training
Oracle PL/SQL online training | PL/SQL online Training
 
SQL / PL
SQL / PLSQL / PL
SQL / PL
 
Oracle etl openworld
Oracle etl openworldOracle etl openworld
Oracle etl openworld
 
Oracel CURSOR AND EXCEPTIONS
Oracel CURSOR AND EXCEPTIONSOracel CURSOR AND EXCEPTIONS
Oracel CURSOR AND EXCEPTIONS
 
L9 l10 server side programming
L9 l10  server side programmingL9 l10  server side programming
L9 l10 server side programming
 
Advanced_SQL_ISASasASasaASnjection (1).ppt
Advanced_SQL_ISASasASasaASnjection (1).pptAdvanced_SQL_ISASasASasaASnjection (1).ppt
Advanced_SQL_ISASasASasaASnjection (1).ppt
 
Chapter8 pl sql
Chapter8 pl sqlChapter8 pl sql
Chapter8 pl sql
 
Oracle Database 12c - The Best Oracle Database 12c Tuning Features for Develo...
Oracle Database 12c - The Best Oracle Database 12c Tuning Features for Develo...Oracle Database 12c - The Best Oracle Database 12c Tuning Features for Develo...
Oracle Database 12c - The Best Oracle Database 12c Tuning Features for Develo...
 
plsql les02
 plsql les02 plsql les02
plsql les02
 

More from Richard Eliseo Mendoza Gafaro

More from Richard Eliseo Mendoza Gafaro (20)

CUESTIONARIO REDES TELEMATICAS CISCO, HPE Y HUAWEI
CUESTIONARIO REDES TELEMATICAS CISCO, HPE Y HUAWEICUESTIONARIO REDES TELEMATICAS CISCO, HPE Y HUAWEI
CUESTIONARIO REDES TELEMATICAS CISCO, HPE Y HUAWEI
 
Material_para_Estudiante_DMPC_V012022A_SP_1
Material_para_Estudiante_DMPC_V012022A_SP_1Material_para_Estudiante_DMPC_V012022A_SP_1
Material_para_Estudiante_DMPC_V012022A_SP_1
 
MANUAL DE ORACLE AUTONOMOUS DATABASE
MANUAL DE ORACLE AUTONOMOUS DATABASEMANUAL DE ORACLE AUTONOMOUS DATABASE
MANUAL DE ORACLE AUTONOMOUS DATABASE
 
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 3
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 3PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 3
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 3
 
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 2
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 2PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 2
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 2
 
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 4
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 4PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 4
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 4
 
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 1
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 1PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 1
PARCIAL 2 PLATAFORMAS Y SOPORTES MULTIMEDIA 2023-2-VARIANTE 1
 
PARCIAL 2 SISTEMAS OPERATIVOS - BD MYSQL EN ORACLE OCI
PARCIAL 2 SISTEMAS OPERATIVOS - BD MYSQL EN ORACLE OCIPARCIAL 2 SISTEMAS OPERATIVOS - BD MYSQL EN ORACLE OCI
PARCIAL 2 SISTEMAS OPERATIVOS - BD MYSQL EN ORACLE OCI
 
PARCIAL 2 DESARROLLO DE INTERFACES UI UX
PARCIAL 2 DESARROLLO DE INTERFACES UI UXPARCIAL 2 DESARROLLO DE INTERFACES UI UX
PARCIAL 2 DESARROLLO DE INTERFACES UI UX
 
Explicación cadena de valor
Explicación cadena de valorExplicación cadena de valor
Explicación cadena de valor
 
MANUAL DESPLIEGUE SERVIDOR WEB
MANUAL DESPLIEGUE SERVIDOR WEBMANUAL DESPLIEGUE SERVIDOR WEB
MANUAL DESPLIEGUE SERVIDOR WEB
 
MANUAL DE DESPLIEGUE BASE DE DATOS CON WORKBENCH
MANUAL DE DESPLIEGUE BASE DE DATOS CON WORKBENCHMANUAL DE DESPLIEGUE BASE DE DATOS CON WORKBENCH
MANUAL DE DESPLIEGUE BASE DE DATOS CON WORKBENCH
 
CUESTIONARIO INTRODUCCION A UNITY 3D v2
CUESTIONARIO INTRODUCCION A UNITY 3D v2CUESTIONARIO INTRODUCCION A UNITY 3D v2
CUESTIONARIO INTRODUCCION A UNITY 3D v2
 
CUESTIONARIO INTRODUCCION A UNITY 3D
CUESTIONARIO INTRODUCCION A UNITY 3DCUESTIONARIO INTRODUCCION A UNITY 3D
CUESTIONARIO INTRODUCCION A UNITY 3D
 
MANUAL DESPLIEGUE SERVIDOR BASE DE DATOS
MANUAL DESPLIEGUE SERVIDOR BASE DE DATOSMANUAL DESPLIEGUE SERVIDOR BASE DE DATOS
MANUAL DESPLIEGUE SERVIDOR BASE DE DATOS
 
INTRODUCCION A SISTEMAS OPERATIVOS
INTRODUCCION A SISTEMAS OPERATIVOSINTRODUCCION A SISTEMAS OPERATIVOS
INTRODUCCION A SISTEMAS OPERATIVOS
 
CLASE 2 ORACLE CLOUD
CLASE 2 ORACLE CLOUDCLASE 2 ORACLE CLOUD
CLASE 2 ORACLE CLOUD
 
CASOS DE ESTUDIO MODELADO DEL NEGOCIO
CASOS DE ESTUDIO MODELADO DEL NEGOCIOCASOS DE ESTUDIO MODELADO DEL NEGOCIO
CASOS DE ESTUDIO MODELADO DEL NEGOCIO
 
MATERIAL DE ESTUDIO CCNA
MATERIAL DE ESTUDIO CCNAMATERIAL DE ESTUDIO CCNA
MATERIAL DE ESTUDIO CCNA
 
PREGUNTAS TOGAF 9.2 RESPUESTAS
PREGUNTAS TOGAF 9.2 RESPUESTASPREGUNTAS TOGAF 9.2 RESPUESTAS
PREGUNTAS TOGAF 9.2 RESPUESTAS
 

Recently uploaded

Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
DeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakesDeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakes
MayuraD1
 
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Kandungan 087776558899
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
AldoGarca30
 
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
HenryBriggs2
 

Recently uploaded (20)

Thermal Engineering Unit - I & II . ppt
Thermal Engineering  Unit - I & II . pptThermal Engineering  Unit - I & II . ppt
Thermal Engineering Unit - I & II . ppt
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdf
 
School management system project Report.pdf
School management system project Report.pdfSchool management system project Report.pdf
School management system project Report.pdf
 
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
 
S1S2 B.Arch MGU - HOA1&2 Module 3 -Temple Architecture of Kerala.pptx
S1S2 B.Arch MGU - HOA1&2 Module 3 -Temple Architecture of Kerala.pptxS1S2 B.Arch MGU - HOA1&2 Module 3 -Temple Architecture of Kerala.pptx
S1S2 B.Arch MGU - HOA1&2 Module 3 -Temple Architecture of Kerala.pptx
 
PE 459 LECTURE 2- natural gas basic concepts and properties
PE 459 LECTURE 2- natural gas basic concepts and propertiesPE 459 LECTURE 2- natural gas basic concepts and properties
PE 459 LECTURE 2- natural gas basic concepts and properties
 
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptxOrlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
 
DeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakesDeepFakes presentation : brief idea of DeepFakes
DeepFakes presentation : brief idea of DeepFakes
 
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptxHOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
 
Jaipur ❤CALL GIRL 0000000000❤CALL GIRLS IN Jaipur ESCORT SERVICE❤CALL GIRL IN...
Jaipur ❤CALL GIRL 0000000000❤CALL GIRLS IN Jaipur ESCORT SERVICE❤CALL GIRL IN...Jaipur ❤CALL GIRL 0000000000❤CALL GIRLS IN Jaipur ESCORT SERVICE❤CALL GIRL IN...
Jaipur ❤CALL GIRL 0000000000❤CALL GIRLS IN Jaipur ESCORT SERVICE❤CALL GIRL IN...
 
Generative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPTGenerative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPT
 
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
457503602-5-Gas-Well-Testing-and-Analysis-pptx.pptx
 
Tamil Call Girls Bhayandar WhatsApp +91-9930687706, Best Service
Tamil Call Girls Bhayandar WhatsApp +91-9930687706, Best ServiceTamil Call Girls Bhayandar WhatsApp +91-9930687706, Best Service
Tamil Call Girls Bhayandar WhatsApp +91-9930687706, Best Service
 
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
Unit 4_Part 1 CSE2001 Exception Handling and Function Template and Class Temp...
 
AIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech studentsAIRCANVAS[1].pdf mini project for btech students
AIRCANVAS[1].pdf mini project for btech students
 
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
💚Trustworthy Call Girls Pune Call Girls Service Just Call 🍑👄6378878445 🍑👄 Top...
 
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
 
Thermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.pptThermal Engineering -unit - III & IV.ppt
Thermal Engineering -unit - III & IV.ppt
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
 
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
scipt v1.pptxcxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx...
 

PL/SQL CURSORES

  • 1. 1
  • 2. 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
  • 42. 42
  • 43. 1
  • 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
  • 70. 28
  • 71. 1
  • 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
  • 92. 22
  • 93. 1
  • 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
  • 111. 19
  • 112. 1
  • 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
  • 128. 17
  • 129. 1
  • 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
  • 143. 15