0% found this document useful (0 votes)
24 views20 pages

Chapter 6 Cursors

Uploaded by

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

Chapter 6 Cursors

Uploaded by

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

CURSORS

create table num


( a int,
b int
)

insert into num values(1,2)


insert into num values(3,1)

insert into num values(22,12)

insert into num values(50,100)

insert into num values(10,9)

a b

1 2
3 1
22 12
50 100
10 9

categorized cursors into the following topics:


Declare a Cursor

OPEN Statement

FETCH Statement

CLOSE Statement

Cursor Attributes (%FOUND, %NOTFOUND, etc)

SELECT FOR UPDATE Statement

WHERE CURRENT OF Statement

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
USING %TYPE

//simple program to select rows from the table using cursors

declare
a1 num.a%type;
b1 num.b%type;
cursor c1 is
select * from num; -- step 1
Begin
open c1; -- step 2
dbms_output.put_line('a' || ' ' || 'b');
dbms_output.put_line('_____________');
loop
fetch c1 into a1,b1;
exit when c1%NOTFOUND; --step 3
dbms_output.put_line(a1 || ' ' || b1);
end loop;
close c1; -- step 4
end;
/

Note:
1. Here I have used *. So we need to declare temp_variables as in the table.
2. If we select 3 columns in SELECT query then we need to declare 3 temp_variable
otherwise error will be raised in red line.

//Above program is implemented using selected columns in table.

declare
a1 num.a%type;
cursor c1 is
select a from num; -- step 1
Begin
open c1; -- step 2
dbms_output.put_line('a');
dbms_output.put_line('___');

loop
fetch c1 into a1;
exit when c1%NOTFOUND; --step 3

dbms_output.put_line(a1);
end loop;
close c1; -- step 4
end;/
By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
// This program will select rows as per the condition and will display to the user

declare
a1 num.a%type;
b1 num.b%type;
cursor c1 is
select a,b from num where a<b; -- step 1
Begin
open c1; -- step 2
dbms_output.put_line('A' || ' ' || 'B');
loop
fetch c1 into a1,b1;
exit when c1%NOTFOUND; --step 3
dbms_output.put_line(a1 ||' '|| b1);
end loop;
close c1; -- step 4
end;
/
//The above program is modified in such a way that when a>b the we need to delete the
current row & to insert row as (b,a) i.e swapping

declare
a1 num.a%type;
b1 num.b%type;
cursor c1 is
select a,b from num where a<b for update; -- step 1
Begin
open c1; -- step 2
dbms_output.put_line('A' || ' ' || 'B');
loop
fetch c1 into a1,b1;
exit when c1%NOTFOUND; --step 3

delete from num where current of c1;


insert into num values(b1,a1);

end loop;

close c1; -- step 4


end;
/

Note: SELECT stat can be as follows for this case:


SELECT * from num where a > b FOR UPDATE ;
SELECT * from num where a> b FOR UPDATE OF a;
By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
USING %ROWTYPE

Note : while using %ROWTYPE no need to use “Temp_ variables”.

// Sample program to implement this %Rowtype

declare
cursor c1 is
select * from num; -- step 1
r_c1 c1%ROWTYPE;
Begin
open c1; -- step 2
loop
fetch c1 into r_c1;
exit when c1%NOTFOUND; --step 3
if r_c1.a > r_c1.b then
dbms_output.put_line(r_c1.a || ' is > than' || r_c1.b);
else
dbms_output.put_line(r_c1.b || ' is > than' || r_c1.a);
end if;
end loop;
close c1; -- step 4
end;
/
Note: in condition you are using two columns a & b. So in SELECT statement you need
to put * or mention both columns.

//The same program is shown by using single column/attribute.

declare
cursor c1 is
select a from num; -- step 1
r_c1 c1%ROWTYPE;
Begin
open c1; -- step 2
loop
fetch c1 into r_c1;
exit when c1%NOTFOUND; --step 3
if( r_c1.a > 35) then
dbms_output.put_line(r_c1.a || ' is > than ' || 35);
end if;
end loop;
close c1; -- step 4
end;
/
By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
CURSOR ARRTIBUTES

Cursor Attributes

Name Description

%FOUND Returns TRUE if record was fetched successfully, FALSE otherwise.

%NOTFOUND Returns TRUE if record was not fetched successfully, FALSE


otherwise.

%ROWCOUNT Returns number of records fetched from cursor at that point in time.

%ISOPEN Returns TRUE if cursor is open, FALSE otherwise.

//This program uses rowcount attribute.


declare
cursor c1 is
select a from num; -- step 1
r_c1 c1%ROWTYPE;
Begin
open c1; -- step 2
loop
fetch c1 into r_c1;
exit when c1%ROWCOUNT > 3 OR c1%NOTFOUND; --step 3
if( r_c1.a > 35) then
dbms_output.put_line(r_c1.a || ' is > than ' || 35);
end if;
end loop;
close c1; -- step 4
end;
// The above Program using ISOPEN attribute
declare
cursor c1 is
select a from num; -- step 1
r_c1 c1%ROWTYPE;
Begin
if NOT c1%ISOPEN then
open c1; -- step 2
end if;
loop
fetch c1 into r_c1;
exit when c1%ROWCOUNT > 3 OR c1%NOTFOUND; --step 3
if( r_c1.a > 35) then
dbms_output.put_line(r_c1.a || ' is > than ' || 35);
By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
end if;
end loop;
close c1; -- step 4
end;
USING WHILE structure To FETCH ROWS

DECLARE
a1 num.a%type;
b1 num.b%type;
CURSOR C1 IS
SELECT * FROM num
where a>3 and b>10;
BEGIN
OPEN C1;
FETCH C1 INTO a1,b1;
WHILE C1%FOUND
LOOP
FETCH C1 INTO a1,b1;
dbms_output.put_line(a1 || ' '|| b1);
END LOOP;
CLOSE C1;
END;
/
Note: two times we need to fetch the row for while loop one inside & one outside.

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Working with REF CURSOR in PL/SQL

A REF CURSOR is basically a data type. A variable created based on such a data type is
generally called a cursor variable. A cursor variable can be associated with different
queries at run-time. The primary advantage of using cursor variables is their capability to
pass result sets between sub programs (like stored procedures, functions, packages etc.).
USING %TYPE

1 declare
2 type r_cursor is REF CURSOR;
3 c1 r_cursor;
4 a1 num.a%type;

5 begin
6 open c1 for select a from num;

7 loop
8 fetch c1 into a1;
9 exit when c1%notfound;
10 dbms_output.put_line(a1);
11 end loop;

12 close c1;
13 end;
/

Explanation:

Step 2 is for defining a cursor r_cursor DATA TYPE which is of type REF CURSOR.
Step 3 Cursor variable is defind of type r_cursor
Step 6 Every cursor must open with associate SELECT statement.

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
USING %ROWTYPE

declare
type rc1 is REF CURSOR;
c1 rc1;
r1 supplier%ROWTYPE;

begin
if NOT c1%ISOPEN then
open c1 for select * from supplier;
end if;

loop
FETCH c1 into r1;
exit WHEN c1%NOTFOUND;
dbms_output.put_line(r1.s||' '|| r1.sname||' '||r1.status||'
'||r1.city);
end loop;
close c1;
end;

Output:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Table Used:

Records in Table:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Working with RECORD and REF CURSOR

Note:

%TYPE à Working with one record.

%ROWTYPE à Working with multiple record.

To create our own data type and specific number of values, We are going to use
TYPE & RECORD.

Note:2

Now a question arises why we are using ref cursor?


We have one answer creating own data type. YES that’s right.
But one more reason is also there.

Consider a scenario. When you use ROWTYPE you are selecting all the columns i.e.
one record completely. Now you want to select only specific columns from one record
and whenever you want to use those specific columns anywhere in PLSQL block we have
to use our own record & own data type.

Tips:
consider we are using VIEW instead of table.( for understanding purpose only, this is
not the concept.)
E.g.:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Now you want to work only with two columns shipment id and destination and consider
this two columns as one complete record.

Let us consider the following example:

declare
type rc2 is REF CURSOR;
c2 rc2;

type rec1 is record


( sid int,
dest char(20)
);
shipment_1 rec1;
begin
open c2 for select shipment_id,destination from shipment2;

loop
fetch c2 into shipment_1;
exit when c2%NOTFOUND;
dbms_output.put_line(shipment_1.sid || ' ' || shipment_1.dest);
end loop;
close c2;

end;

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Output:

Explanations:

type rec1 is record


( sid int,
dest char(20)
);
The above defines a new data type named "shipment_1" (just like %ROWTYPE with
limited specified fields) which can hold two fields, namely "sid" and "dest."

shipment_1 rec1;

The above statement declares a variable "shipment_1er" based on the data type
"rec1." This means that "shipment_1" internally contains the fields "sid" and "dest."

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Working with more than one query with the same REF CURSOR

declare
type rc2 is REF CURSOR;
c2 rc2;
type rec1 is record
( sid int,
dest char(20)
);

shipment_1 rec1;
begin
-- 1st query
open c2 for select shipment_id,destination from shipment2 where
shipment_id = 110;

loop
fetch c2 into shipment_1;
exit when c2%NOTFOUND;
dbms_output.put_line(shipment_1.sid || ' ' || shipment_1.dest);
end loop;
close c2;

-- 2nd query
open c2 for select shipment_id,destination from shipment2 where
shipment_id = 114;

loop
fetch c2 into shipment_1;
exit when c2%NOTFOUND;
dbms_output.put_line(shipment_1.sid || ' ' || shipment_1.dest);
end loop;
close c2;
end;
Output:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Working with REF CURSOR inside loops

declare
type rc2 is REF CURSOR;
c2 rc2;
type rec1 is record
( cid int,
dest char(20)
);

rec_ship rec1;
begin
for i in (select shipment_id, ship_date from shipment2) -- any
columns but only 2
loop
open c2 for select cust_id,destination from shipment2
where shipment_id = i.shipment_id;
dbms_output.put_line(i.ship_date);
dbms_output.put_line('__________');
loop
fetch c2 into rec_ship;
exit when c2%NOTFOUND;
dbms_output.put_line(rec_ship.cid || ' '||
rec_ship.dest );
end loop;
close c2;z`
end loop;
end;

Explanation:
for i in (select shipment_id, ship_date from shipment2)
loop
.
.
end loop;
The above loop iterates continuously for each row of the "shipment2" table. The details
of each row in "shipment2t" (like shipment_id, ship_date etc.) will be available in
the variable "i." Using that variable (as part of the SELECT statement), then working
with REF CURSOR as follows:
open c2 for select cust_id,destination from shipment2
where shipment_id = i.shipment_id;

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Output:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Dealing with REF CURSOR in the sub-programs of a PL/SQL block
For easy understanding consider the above PLSQL code,
declare
type rc2 is REF CURSOR;
c2 rc2;
type rec1 is record
( cid int,
dest char(20)
);

rec_ship rec1;
begin
for i in (select shipment_id, ship_date from shipment2) -- any
columns but only 2
loop
open c2 for select cust_id,destination from shipment2
where shipment_id = i.shipment_id;
dbms_output.put_line(i.ship_date);
dbms_output.put_line('__________');
loop
fetch c2 into rec_ship;
exit when c2%NOTFOUND;
dbms_output.put_line(rec_ship.cid || '
'|| rec_ship.dest );
end loop;
close c2;z`
end loop;
end;

Note:
To use ref cursor in sub programs, put the highlighted code into the procedure. See the
code below:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
declare

type rc2 is REF CURSOR;


c2 rc2;

type rec1 is record


( cid int,
dest char(20)
);

rec_ship rec1;

procedure p_ref is
begin
loop
fetch c2 into rec_ship;
exit when c2%NOTFOUND;
dbms_output.put_line(rec_ship.dest);
end loop;
end;

begin
for i in (select shipment_id, ship_date from shipment2) -- any
columns but only 2
loop
open c2 for select cust_id,destination from shipment2
where shipment_id = i.shipment_id;
dbms_output.put_line(i.ship_date);
dbms_output.put_line('__________');

p_ref;
end loop;

end;

Explanation:

for i in (select shipment_id, ship_date from shipment2)

loop
.
.
p_ref;
.
.
end loop;
According to the above loop, the sub-routine gets executed for every iteration, which
displays the employee information for the respective department.

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Output:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Passing REF CURSOR as parameters to sub-programs

v Every sub-program (or sub-routine) can accept values passed to it in the form of
"parameters" (or arguments).
v Every parameter is very similar to a variable, but gets declared as part of a sub-
program.
declare

type rc2 is REF CURSOR;


c2 rc2;

type rec1 is record


( cid int,
dest char(20)
);

procedure p_ref(pc2 rc2) is


(or) procedure p_ref ( pc2 c2%TYPE )

rec_ship rec1;
begin
loop
fetch c2 into rec_ship;
exit when c2%NOTFOUND;
dbms_output.put_line(rec_ship.dest);
end loop;
end;
begin
for i in (select shipment_id, ship_date from shipment2) -- any
columns but only 2
loop
open c2 for select cust_id,destination from shipment2 where
shipment_id = i.shipment_id;
dbms_output.put_line(i.ship_date);
dbms_output.put_line('__________');

p_ref(c2);
end loop;

end;

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal
Output:

By dinesh

By S. DINESH KUMAR Empid: 56971 Birlasoft Ltd


Classification: Internal

You might also like