1
PL/SQL (Cont’d)
Let’s start with the mail_order database, shown here:
2
Table schemas for the Mail Order database:
3
The values inserted into zipcodes table:
The values inserted into employees table:
4
The values inserted into customers table:
The values inserted into parts table:
5
The values inserted into orders table:
The values inserted into Odetails table:
6
First PL/SQL program which actually uses SQL statement within the body of the program:
a. The following is an example of an anonymous block
b. The block gets all the rows from the MO_customers table
c. It prints the names of the customers on the screen
d. It does use PL/SQL tables and cursors (covered later)
e. To execute this anonymous block within the SQLPLUS environment, save it in a *.sql file
f. Use start *.sql at the sql prompt to execute it
g. All rows of MO-customer is redefined as a table type and is called customers_table
h. The alias c_table is used for customers_table
i. The sql statement is declared as cursor ‘c’
j. The explicit (vs. implicit) cursor ‘c’ is defined as select … from MO_customers
k. …
7
PL/SQL/Cursors
Oracle creates a memory area, known as context area, for processing an SQL statement, which contains all information needed for processing the statement, for example, number of rows processed, etc.
A cursor is a pointer to this context area. PL/SQL controls the context area through a cursor. A cursor holds the rows (one or more) returned by a SQL statement. The set of rows the cursor holds is referred to as the active set.
You can name a cursor so that it could be referred to in a program to fetch and process the rows returned by the SQL statement, one at a time. There are two types of cursors:
Implicit cursors
Explicit cursors
Implicit Cursors
Implicit cursors are automatically created by Oracle whenever an SQL statement is executed, when there is no explicit cursor for the statement. Programmers cannot control the implicit cursors and the information in it.
Whenever a DML statement (INSERT, UPDATE and DELETE) is issued, an implicit cursor is associated with this statement. For INSERT operations, the cursor holds the data that needs to be inserted. For UPDATE and DELETE operations, the cursor identifies the rows that would be affected.
In PL/SQL, you can refer to the most recent implicit cursor as the SQL cursor, which always has the attributes like %FOUND, %ISOPEN, %NOTFOUND, and %ROWCOUNT. The SQL cursor has additional attributes, %BULK_ROWCOUNT and %BULK_EXCEPTIONS, designed for use with the FORALL statement. The following table provides the description of the most used attributes:
Attribute Description
%FOUND Returns TRUE if an INSERT, UPDATE, or DELETE statement affected one or more rows or a SELECT INTO statement returned one or more rows. Otherwise, it returns FALSE.
%NOTFOUND The logical opposite of %FOUND. It returns TRUE if an INSERT, UPDATE, or DELETE statement affected no rows, or a SELECT INTO statement returned no rows. Otherwise, it returns FALSE.
%ISOPEN Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor automatically after executing its associated SQL statement.
%ROWCOUNT Returns the number of rows affected by an INSERT, UPDATE, or DELETE statement, or returned by a SELECT INTO statement.
Any SQL cursor attribute will be accessed as sql%attribute_name as shown below in the example.
Before talking about implicit and explicit cursors, think about the following two examples:
x = x + 1; or x = x + y (long version/Explicit) or the short version/implicit of them: x ++; or x += y;
8
Implicit Cursors Example
There are 5 records in the employee table, with empid, dept, salary, hiredate, supervisorid as attributes.
Sample table employee before introducing the implicit cursors (sql%found and %notfound):
The following procedure counts the number of records in the employee table and increases the salaries
of all employees by 500, and displays the updated contents of the table.
The display of the total_rows = 5 is not shown in the above screen capture.
9
More Examples:
The cursor loads one tuple(row) into the context area, whereas the sql statement following
PL/SQL program retrieves all tuples of the table.
How would you retrieve all rows using the PL/SQL program? How about placing the fetch
statement inside a loop, iterating till all tuples are counted for? Let’s do it (see next page).
10
The following loop is much more efficient and does the same.
11
Question 1: What does the following program do? Table x has 3 rows (1, 1, 1; 2, 4, 8; 3, 9, 27).
Your Answer:
12
Question 2: What does the following program do? Table x has 3 rows (1, 1, 1; 2, 4, 8; 3, 9, 27).
Your answer:
13
More on Explicit Cursors
Explicit cursors are programmer defined cursors for gaining more control over the context area. An explicit cursor should be defined in the declaration section of the PL/SQL Block. It is created on a SELECT Statement which returns more than one row.
The syntax for creating an explicit cursor is :
CURSOR cursor_name IS select_statement;
Working with an explicit cursor involves four steps:
Declaring the cursor for initializing in the memory
Opening the cursor for allocating memory
Fetching the cursor for retrieving data
Closing the cursor to release allocated memory
Declaring the Cursor
Declaring the cursor defines the cursor with a name and the associated SELECT statement. For example:
CURSOR c_customers IS
SELECT id, name, address FROM customers;
Opening the Cursor
Opening the cursor allocates memory for the cursor and makes it ready for fetching the rows returned by the SQL statement into it. For example, we will open above-defined cursor as follows:
OPEN c_customers;
Fetching the Cursor
Fetching the cursor involves accessing one row at a time. For example we will fetch rows from the above-opened cursor as follows:
FETCH c_customers INTO c_id, c_name, c_addr;
Closing the Cursor
Closing the cursor means releasing the allocated memory. For example, we will close above-opened cursor as follows:
CLOSE c_customers;
Think of the cursor as a pointer to the beginning of the table/ later moves down with fetch statement
Name … type … initialization (amount number := 0;) Type … name … initialization (cursor a_cur is select * from x;) Open allocates memory for the cursor & makes it ready for fetching the rows returned by sql statement Fetch the cursor involves one row at a time loaded in the variables and return to the beginning of the next Close is like unloading the table and releasing the allocated memory
14
Additional Explicit Cursors Examples
Using the employee table with 5 records, with empid, dept, salary, hiredate, supervisorid as attributes:
a. Sample table employee before introducing the implicit cursors (sql%found and %notfound):
b. The original table attributes (empid, dept, and salary) are renamed as e_id, e_dept, e_sal
c. The cursor is declared as e_employee (still in DECLARE block)
d. In the BEGIN block, the cursor is opened
e. The rows are fetched one by one until the implicit cursor %notfound is true (no employees left)
f. The loop ends after fetching 5 records and the cursor is closed
g. Fetch goes forward, one row at a time, it cannot jump for row 1 to row 6, or go backward
15
Another Example
The following is another example of using cursor statements (cursor, open, fetch, …) and attributes:
PL/SQL provides a variation of for loop to be used with cursors, useful in situations where all rows of the
cursor are to be processed, with the following syntax:
for <record_index> in <cname> loop loop body; end loop; Here is the previous program with this for statement (no open, fetch, or close the cursor needed, as the
loop terminates automatically when all rows of the cursor are fetched):
16
Parametrized Cursors
PL/SQL allows cursors to take input parameters, which makes them more flexible. The syntax foe
declaring explicit cursor with parameters, specified immediately after the cursor name, is:
Cursor <Cname> (<parameter-list>) [return <return-spec>] Is <select-statement>;
Question:
How would you modify the program to display all employees, cities, and total sales?
17
PL/SQL Records
A PL/SQL record is a data structure that can hold data items of different kinds. Records consist of different fields, similar to a row of a database table.
For example, you want to keep track of your books in a library. You might want to track the following attributes about each book like, Title, Author, Subject, Book ID. A record containing a field for each of these items allows treating a BOOK as a logical unit and allows you to organize and represent its information in a better way.
PL/SQL can handle the following types of records:
Table-based
Cursor-based records
User-defined records
Table-Based Records
The %ROWTYPE attribute enables a programmer to create table-based and cursor-based records.
The following example would illustrate the concept of table-based records. We will be using the employee table we had created and used in the previous examples:
Review Exercise:
Modify the above program so that it will display the same information about all the employees in the
table employee, not just the one with empid = 1001.
18
Cursor-Based Records
The following example would illustrate the concept of cursor-based records. We will be using the CUSTOMERS table we had created and used in the previous examples:
User-Defined Records PL/SQL provides a user-defined record type that allows you to define different record structures. Records consist of different fields. Suppose you want to keep track of your books in a library. You might want to track the following attributes about each book:
Title
Author
Subject
Book ID
Defining a Record
The record type is defined as:
TYPE type_name IS RECORD ( field_name1 datatype1 [NOT NULL] [:= DEFAULT EXPRESSION], field_name2 datatype2 [NOT NULL] [:= DEFAULT EXPRESSION], ... field_nameN datatypeN [NOT NULL] [:= DEFAULT EXPRESSION); record-name type_name;
19
Here is the way you would declare the Book record:
DECLARE TYPE books IS RECORD (title varchar(50), author varchar(50), subject varchar(100), book_id number); book1 books; book2 books;
Here is an example of implementation of the user-defined records:
20
Homework:
Given the following investment portfolio database, complete the PL/SQL programs on the following
page. A sample of investment portfolio database:
21