0% found this document useful (0 votes)
39 views44 pages

Week 10 Cursor

This document discusses PL/SQL cursors and how to retrieve and manipulate data using cursors in PL/SQL. It covers implicit and explicit cursors, declaring a cursor, opening a cursor, fetching rows from a cursor, testing if a cursor is empty, and closing a cursor. Loops such as basic loops, while loops, and for loops are also discussed for iterating through cursor results.

Uploaded by

Anonymous
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
39 views44 pages

Week 10 Cursor

This document discusses PL/SQL cursors and how to retrieve and manipulate data using cursors in PL/SQL. It covers implicit and explicit cursors, declaring a cursor, opening a cursor, fetching rows from a cursor, testing if a cursor is empty, and closing a cursor. Loops such as basic loops, while loops, and for loops are also discussed for iterating through cursor results.

Uploaded by

Anonymous
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PPT, PDF, TXT or read online on Scribd
You are on page 1/ 44

PL/SQL CURSORS

SELECT Statements in PL/SQL

Retrieve data from the database with a SELECT


statement.
Syntax:
SELECT select_list
INTO {variable_name[, variable_name]...
| record_name}
FROM table
[WHERE condition];
SELECT Statements in PL/SQL

• The INTO clause is required.


• Queries must return only one row.
Example
SET SERVEROUTPUT ON
DECLARE
fname VARCHAR2(25);
BEGIN
SELECT first_name INTO fname
FROM employees WHERE employee_id=200;
DBMS_OUTPUT.PUT_LINE(' First Name is : '||fname);
END;
/
Retrieving Data in PL/SQL

Retrieve the hire_date and the salary for the


specified employee.

Example
DECLARE
emp_hiredate employees.hire_date%TYPE;
emp_salary employees.salary%TYPE;
BEGIN
SELECT hire_date, salary
INTO emp_hiredate, emp_salary
FROM employees
WHERE employee_id = 100;
END;
/
Retrieving Data in PL/SQL

Return the sum of the salaries for all the employees in


the specified department.

Example
SET SERVEROUTPUT ON
DECLARE
sum_sal NUMBER(10,2);
deptno NUMBER NOT NULL := 60;
BEGIN
SELECT SUM(salary) -- group function
INTO sum_sal FROM employees
WHERE department_id = deptno;
DBMS_OUTPUT.PUT_LINE ('The sum of salary is '
|| sum_sal);
END;
/
Manipulating Data Using PL/SQL

Make changes to database tables by using DML


commands:
• INSERT
DELETE
• UPDATE
• DELETE

INSERT

UPDATE
Inserting Data

Add new employee information to the EMPLOYEES


table.

Example
BEGIN
INSERT INTO employees
(employee_id, first_name, last_name, email,
hire_date, job_id, salary)
VALUES(employees_seq.NEXTVAL, 'Ruth', 'Cores',
'RCORES',sysdate, 'AD_ASST', 4000);
END;
/
SQL Cursor

• A cursor is a pointer to the private memory


area allocated by the Oracle server.
• There are two types of cursors:
– Implicit: Created and managed internally by
the Oracle server to process SQL statements
– Explicit: Explicitly declared by the
programmer
IMPLICIT CURSORS

-Any given PL/SQL block issues an implicit cursor


whenever an SQL statement is executed (as long as an
explicit cursor does not exist for that SQL statement)
-A cursor is automatically associated with every DML
statement
-All update and delete statements have cursors that
identify the set of rows that will be affected by the operation
-The most recently opened cursor is called ‘SQL%’ cursor.
SQL Cursor Attributes for Implicit Cursors

Using SQL cursor attributes, you can test the outcome


of your SQL statements.
SQL%FOUND Boolean attribute that evaluates to TRUE if the most
recent SQL statement returned at least one row

SQL%NOTFOUND Boolean attribute that evaluates to TRUE if


the most recent SQL statement did not
return even one row

SQL%ROWCOUNT An integer value that represents the number of rows


affected by the most recent SQL statement
SQL Cursor Attributes for Implicit Cursors- an
example - update

BEGIN
UPDATE S
SET status = 40
WHERE status = 30;
DBMS_OUTPUT.PUT_LINE('Number of updates = '||
SQL%ROWCOUNT);
END;
/
SQL Cursor Attributes for Implicit Cursors –
another example - delete

Delete rows that have the specified employee ID


from the employees table. Print the number of
rows deleted.

Example
--VARIABLE rows_deleted VARCHAR2(30)
DECLARE
empno employees.employee_id%TYPE := 176;
BEGIN
DELETE FROM employees
WHERE employee_id = empno;
rows_deleted := (SQL%ROWCOUNT ||
' row deleted.');
END;
/
PRINT rows_deleted
Controlling Flow of Execution

for
loop

while
IF Statements

Syntax:
IF condition THEN
statements;
[ELSIF condition THEN
statements;]
[ELSE
statements;]
END IF;
IF ELSIF ELSE Clause
DECLARE
myage number:=31;
BEGIN
IF myage < 11
THEN
DBMS_OUTPUT.PUT_LINE(' I am a child ');
ELSIF myage < 20
THEN
DBMS_OUTPUT.PUT_LINE(' I am young ');
ELSIF myage < 30
THEN
DBMS_OUTPUT.PUT_LINE(' I am in my twenties');
ELSIF myage < 40
THEN
DBMS_OUTPUT.PUT_LINE(' I am in my thirties');
ELSE
DBMS_OUTPUT.PUT_LINE(' I am always young ');
END IF;
END;
/
CASE Expressions

• A CASE expression selects a result and returns it.


• To select the result, the CASE expression uses
expressions. The value returned by these
expressions is used to select one of several
alternatives.
CASE selector
WHEN expression1 THEN result1
WHEN expression2 THEN result2
...
WHEN expressionN THEN resultN
[ELSE resultN+1]
END;
/
CASE Expressions: Example

SET SERVEROUTPUT ON
SET VERIFY OFF
DECLARE
grade CHAR(1) := UPPER('&grade');
appraisal VARCHAR2(20);
BEGIN
appraisal :=
CASE grade
WHEN 'A' THEN 'Excellent'
WHEN 'B' THEN 'Very Good'
WHEN 'C' THEN 'Good'
ELSE 'No such grade'
END;
DBMS_OUTPUT.PUT_LINE ('Grade: '|| grade || '
Appraisal ' || appraisal);
END;
/
Iterative Control: LOOP Statements

• Loops repeat a statement or sequence of


statements multiple times.
• There are three loop types:
– Basic loop
– FOR loop
– WHILE loop
Basic Loops

Syntax:
LOOP
statement1;
. . .
EXIT [WHEN condition];
END LOOP;
Basic Loops

Example
DECLARE
countryid locations.country_id%TYPE := 'CA';
loc_id locations.location_id%TYPE;
counter NUMBER(2) := 1;
new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO loc_id FROM locations
WHERE country_id = countryid;
LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((loc_id + counter), new_city, countryid);
counter := counter + 1;
EXIT WHEN counter > 3;
END LOOP;
END;
/
WHILE Loops

Syntax:
WHILE condition LOOP
statement1;
statement2;
. . .
END LOOP;

Use the WHILE loop to repeat statements while a


condition is TRUE.
WHILE Loops

Example
DECLARE
countryid locations.country_id%TYPE := 'CA';
loc_id locations.location_id%TYPE;
new_city locations.city%TYPE := 'Montreal';
counter NUMBER := 1;
BEGIN
SELECT MAX(location_id) INTO loc_id FROM locations
WHERE country_id = countryid;
WHILE counter <= 3 LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((loc_id + counter), new_city, countryid);
counter := counter + 1;
END LOOP;
END;
/
FOR Loops

• Use a FOR loop to shortcut the test for the number


of iterations.
• Do not declare the counter; it is declared implicitly.
• 'lower_bound .. upper_bound' is required
syntax.

FOR counter IN [REVERSE]


lower_bound..upper_bound LOOP
statement1;
statement2;
. . .
END LOOP;
FOR Loops

Example
DECLARE
countryid locations.country_id%TYPE := 'CA';
loc_id locations.location_id%TYPE;
new_city locations.city%TYPE := 'Montreal';
BEGIN
SELECT MAX(location_id) INTO loc_id
FROM locations
WHERE country_id = countryid;
FOR i IN 1..3 LOOP
INSERT INTO locations(location_id, city, country_id)
VALUES((loc_id + i), new_city, countryid );
END LOOP;
END;
/
Cursors

Every SQL statement executed by the Oracle server


has an associated individual cursor:
• Implicit cursors: Declared and managed by
PL/SQL for all DML and PL/SQL SELECT
statements
• Explicit cursors: Declared and managed by the
programmer
Explicit Cursor Operations

Table
100 King AD_PRES
101 Kochhar AD_VP
Active set
102 De Haan AD_VP
. . .
. . .
. . .
139 Seo ST_CLERK
140 Patel ST_CLERK
. . .
Controlling Explicit Cursors

No

Yes
DECLARE OPEN FETCH EMPTY? CLOSE

• Create a • Identify the • Load the • Test for • Release the


named active set. current existing active set.
SQL area. row into rows.
variables.
• Return to
FETCH if
rows are
found.
Controlling Explicit Cursors

1 Open the cursor.


Cursor
pointer

2 Fetch a row.
Cursor
pointer

Cursor
3 Close the cursor. pointer
Declaring the Cursor

Syntax:
CURSOR cursor_name IS
select_statement;

Examples
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
DECLARE
locid NUMBER:= 1700;
CURSOR dept_cursor IS
SELECT * FROM departments
WHERE location_id = locid;
...
Opening the Cursor

DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
...
BEGIN
OPEN emp_cursor;
Fetching Data from the Cursor

SET SERVEROUTPUT ON
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
empno employees.employee_id%TYPE;
lname employees.last_name%TYPE;
BEGIN
OPEN emp_cursor;
FETCH emp_cursor INTO empno, lname;
DBMS_OUTPUT.PUT_LINE( empno ||' '||lname);
...
END;
/
Fetching Data from the Cursor

SET SERVEROUTPUT ON
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
empno employees.employee_id%TYPE;
lname employees.last_name%TYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO empno, lname;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( empno ||' '||lname);
END LOOP;
...
END;
/
Closing the Cursor

...
LOOP
FETCH emp_cursor INTO empno, lname;
EXIT WHEN emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE( empno ||' '||lname);
END LOOP;
CLOSE emp_cursor;
END;
/
%TYPE and %ROWTYPE attributes

-%ROWTYPE is for records as %TYPE is for fields

-The %ROWTYPE attribute provides a record type that


represents a row in a database table. The record can
store an entire row of data selected from the table or
fetched from a cursor or cursor variable. Variables
declared using %ROWTYPE are treated like those
declared using a datatype name. You can use the
%ROWTYPE attribute in variable declarations as a
datatype specifier.
%TYPE and %ROWTYPE attributes

- Fields in a record and corresponding columns in a row


have the same names and datatypes. However, fields in a
%ROWTYPE record do not inherit constraints, such as the
NOT NULL column or check constraint, or default values

- Both %TYPE and %ROWTYPE are used to define variables


in PL/SQL as it is defined within the database. If the datatype
or precision of a column changes, the program automatically
picks up the new definition from the database without having
to make any code changes.

- The %TYPE and %ROWTYPE constructs provide data


independence, reduces maintenance costs, and allows
programs to adapt as the database changes to meet new
business needs.
Cursors and Records

Process the rows of the active set by fetching values


into a PL/SQL record.
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
emp_record emp_cursor%ROWTYPE;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO emp_record;
...
Cursor FOR Loops

Syntax:
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;

• The cursor FOR loop is a shortcut to process


explicit cursors.
• Implicit open, fetch, exit, and close occur.
• The record is implicitly declared.
Cursor FOR Loops

SET SERVEROUTPUT ON
DECLARE
CURSOR emp_cursor IS
SELECT employee_id, last_name FROM employees
WHERE department_id =30;
BEGIN
FOR emp_record IN emp_cursor
LOOP
DBMS_OUTPUT.PUT_LINE( emp_record.employee_id
||' ' ||emp_record.last_name);
END LOOP;
END;
/
Explicit Cursor Attributes

Obtain status information about a cursor.


Attribute Type Description

%ISOPEN Boolean Evaluates to TRUE if the cursor is


open
%NOTFOUND Boolean Evaluates to TRUE if the most recent
fetch does not return a row
%FOUND Boolean Evaluates to TRUE if the most recent
fetch returns a row; complement of
%NOTFOUND
%ROWCOUNT Number Evaluates to the total number of
rows returned so far
%ISOPEN Attribute

• Fetch rows only when the cursor is open.


• Use the %ISOPEN cursor attribute before
performing a fetch to test whether the cursor is
open.
Example
IF NOT emp_cursor%ISOPEN THEN
OPEN emp_cursor;
END IF;
LOOP
FETCH emp_cursor...
%ROWCOUNT and %NOTFOUND: Example

SET SERVEROUTPUT ON
DECLARE
empno employees.employee_id%TYPE;
ename employees.last_name%TYPE;
CURSOR emp_cursor IS SELECT employee_id,
last_name FROM employees;
BEGIN
OPEN emp_cursor;
LOOP
FETCH emp_cursor INTO empno, ename;
EXIT WHEN emp_cursor%ROWCOUNT > 10 OR
emp_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(TO_CHAR(empno)
||' '|| ename);
END LOOP;
CLOSE emp_cursor;
END ;
/
Cursor FOR Loops Using Subqueries

There is no need to declare the cursor.


Example
SET SERVEROUTPUT ON
BEGIN
FOR emp_record IN (SELECT employee_id, last_name
FROM employees WHERE department_id =30)
LOOP
DBMS_OUTPUT.PUT_LINE( emp_record.employee_id ||'
'||emp_record.last_name);
END LOOP;
END;
/
Cursors with Parameters

Syntax:
CURSOR cursor_name
[(parameter_name datatype, ...)]
IS
select_statement;

• Pass parameter values to a cursor when the


cursor is opened and the query is executed.
• Open an explicit cursor several times with a
different active set each time.
OPEN cursor_name(parameter_value,.....) ;
Cursors with Parameters

SET SERVEROUTPUT ON
DECLARE
CURSOR emp_cursor (deptno number)IS
SELECT employee_id, last_name
FROM employees
WHERE department_id = deptno;
dept_id NUMBER;
lname VARCHAR2(15);
BEGIN
OPEN emp_cursor (10);
...
CLOSE emp_cursor;
OPEN emp_cursor (20);
...

You might also like