Login   Search
Skip Navigation Links
Home
Application Security Tips
Oracle , PL/SQL
IT Product Reviews
Project Management
Forum
Contact Us
Links & References
Avoid SQL Injection attack
Threats and Countermeasures: S.T.R.I.D.E
Input Validation
Session Management
Authentication Mechanism
Cross Site Scripting Vulnerabilities
Configuration Management
Scroll up
Scroll down
Oracle 9i - Programming basics PL/SQL
PL/SQL - Conditional Statements – IF
PL/SQL -Nested Block
LOOPS in PL/SQL
PL/SQL Records
Cursors in PL/SQL
PL/SQL Tables
PL/SQL Exceptions
PL/SQL Procedures
PL/SQL Functions
Oracle supplied packages
Packages
PL/SQL Ref Cursors
Types in Oracle PL/SQL
Varrays
Nested Table
Bfile and LOBs
Bulk Binding
Know Depandencies
PL/SQL Wrapper
Triggers
Scroll up
Scroll down
DBMS_SQL package
DBMS_DDL Package
DBMS_JOB Package
UTL_FILE Package
DBMS_METADATA Package
DBMS_PIPE Package
DBMS_SESSION Package
Scroll up
Scroll down

 

Blog

  • Imperativeness of agile methodology in software development
  • Get list of installed softwares on machines in your network
  • VMWare - Error - the vmware authorization service is not running
  • Add chart / graphs in ASP.net application / website
  • Microsoft Ramp Up

Blog

  • Review: uCertify.com: PrepKit for: 70-529 (C#)
  • Bird eye Review: uCertify.com: PrepKit for: 70-529 (C#)
Skip Navigation Links>Oracle , PL/SQL>Cursors in PL/SQL

Cursors

To process a SQL statement, PL/SQL opens a work area called a context area.
PL/SQL uses this area to execute SQL statements and store processing information
A PL/SQL construct called ‘Cursor’ allows you to name a context area, access its information and in some cases, control its processing

Explicit Cursors
Defined by the user to keep track of which row is being processed, when a query returns multiple rows
 
Defining a Cursor
A cursor is defined in the declarative part of the PL/SQL block by naming it and associating it with a query
CURSOR <cursorname> IS
 SELECT statement;

Example
CURSOR emp_cur IS
SELECT empno, ename, job, sal
FROM emp;
 
A Cursor can be manipulated using
– OPEN
– FETCH
– CLOSE

Cursor must be declared before it can be referenced using the OPEN, CLOSE or FETCH statements
 
The OPEN Statement
    Initializes or opens a cursor
    Cursor must be opened before any rows are returned by the query
OPEN <cursorname>
Example --
           OPEN emp_cur;
 
The FETCH Statement
    Can be executed repeatedly until all rows have been retrieved
FETCH <cursorname> INTO var1, …, varN;
OR
FETCH <cursorname> INTO record_variable;
    Example
FETCH emp_cur INTO mrec;
 
The CLOSE Statement
    Closes the cursor and makes the active set undefined
CLOSE <cursorname>;
    Example
CLOSE emp_cur;
 
Once a cursor is closed, it can be reopened by using the OPEN statement
 
Attributes of Explicit Cursors

Every cursor has four attributes that can be used to access the cursor’s context area
%NOTFOUND
%FOUND
%ROWCOUNT
%ISOPEN

To use these attributes, simple append them to the name of the cursor
%NOTFOUND
evaluates to TRUE if last FETCH failed because no more rows were available
evaluates to FALSE if last FETCH returned a row

%FOUND
evaluates to TRUE if last FETCH returned a row
evaluates to FALSE if last FETCH failed because no more rows were available

%ROWCOUNT
returns the number of rows FETCHed from the active set so far

%ISOPEN
evaluates to TRUE if an explicit cursor is open
evaluates to FALSE if an explicit cursor is closed


Examples of Cursor –
1) To transfer names and sal of employees from emp table where sal >= 2500 in table try1
create table try1
(SERIAL_NO number,
ename varchar2(50),
sal number);
 
Declare
 Cursor cf is
 select ename,sal
 from emp
 where sal >= 2500;
 M cf%rowtype;
 N number;
Begin
 Open cf;
  N := 0;
 Loop
  Fetch cf into M;
        Exit when cf%notfound;
        N := cf%rowcount;
  Insert into try1
 
  values(N,M.ename,M.sal);
 
 End Loop;
 Close cf;
 End;
 
2) Use of %FOUND attribute  
 
Accepting the job from user and finally showing how many such jobs are there.
Declare
       Cursor cf is
             select *
             from emp
             where job ='&J';
 
       M cf%rowtype;
       N number;
       J Emp.Job%type;
 
Begin
 
 Open cf;
 
 N := 0;
 
 Loop
 
  Fetch cf into M;
 
  Exit when cf%notfound;
 
   If cf%found then
 
   N := N + 1;
  End if;
 
 End Loo;
 
 Close cf;
 
 If N > 0 then
  dbms_output.put_line('Total number of job ' || J || ' is '|| N);
 
 else
 
  dbms_output.put_line('No such job');
 
 End If;
End;

----------------------------------------------------------------------
 
3) Use of IsOpen attribute
 Declare
 
 Cursor cf is
 
  select ename, deptno
 
  from emp
 
 where deptno = 20;
 
 M cf%rowtype;
 /*The cursor is not opened before Loop. So using IsOpen attribute to open the 
 cursor if it is not open.*/
 Begin
 /*   Cursor is not opened!!! */
 Loop
  If cf%IsOpen then
   Fetch cf into M;
  else
   Open cf;
   dbms_output.put_line('Cursor is now opened');
  End if;
  exit when cf%notfound;
  dbms_output.put_line(M.ename ||'--' || M.deptno);
 End Loop;
 End;
       --------------------------------------------------------------------------------------

4) Transferring the first five records from emp table into another table FirstFive
 
create table firstfive
as
 select empno,ename,sal,deptno
 from emp
 where 1=2;
Declare
Cursor cf is
 Select *
 from emp;
M cf%rowtype;
 
N number;
Begin

Open cf;
 N := 1; 
 while N <= 5
 Loop 
 Fetch cf into M;

  Insert into firstfive
  values(M.empno,M.ename,M.sal,M.deptno);
  N := N +1;
 End Loop;
End;

5) Displaying the 3rd record entered in the table emp –
 
Declare
  Cursor cf is
    select *
     from emp;
    M cf%rowtype;
Begin
 Open cf;
        Loop
                 fetch cf into M;
                    if cf%rowcount = 3 then
                       dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno);
                        --EXIT;
                   end if;
                  exit when cf%notfound;
        End Loop;
End;
 
 
6) To see the first person( or first record entered) who has got salary > 2800

Declare
 Cursor cf is
    select *
     from emp
      where sal > 2800;
    M cf%rowtype;
Begin
 Open cf;
        Loop
                 fetch cf into M;
                    if cf%rowcount = 1 then
                       dbms_output.put_line(M.empno||'-'||M.ename||'-'||M.sal||'-'||M.deptno);
                           exit;
                   end if;
 
        End Loop;
End;
 
Cursor FOR Loop
Implicitly declares its loop index as a record of %ROWTYPE,
Implicitly opens the cursor
Repeatedly fetches rows of values from the active set into fields in the record
Implicitly closes the cursor when all rows have been processed or the loop is exited
The statements in the loop construct are executed once for each row that satisfies the query associated with the cursor name
Cursor FOR loop is used to simplify coding
No need of --
1)Open cursor
2)Fetch
3)Exit
4)Close cursor
 
7) To show records where salary is > 3000
Declare
 Cursor cf is
     select *
     from emp
     where sal >= 3000;
Begin
   For mrec in cf
        Loop
                  dbms_output.put_line(mrec.ename||' '||mrec.sal||' '||mrec.deptno);
         End Loop;
End;
 
For Loops using sub queries
       No need of declaring cursor.
 
A private cursor within an anonymous block can be created.
 To show names of employees who have job MANAGER.
 
begin
for MREC in (select * from emp)
    Loop 
 if MREC.job = 'MANAGER' then
           dbms_output.put_line('Name is ' ||MREC.ename);
           end if;
    END LOOP;
 
for MREC in (select * from DEPT)
    Loop
      --    if MREC. = 'MANAGER' then
           dbms_output.put_line('Name is ' ||MREC.DNAME);
      -- end if;
    END LOOP;
end;

Parameterized Cursor
The same cursor can be reopened and closed with different active sets.
 
declare
cursor cf(pjob emp.job%type)
is
select empno,ename,job,sal
from emp
where job = pjob;
M cf%rowtype;
begin
 open cf('ANALYST');
 LOOP
     FETCH CF INTO M;
     EXIT WHEN CF%NOTFOUND;
     dbms_output.put_line(‘ANALYST à ‘|| M.ename);
 end loop;
 close cf;
open cf('CLERK');
 LOOP
     FETCH CF INTO M;
     EXIT WHEN CF%NOTFOUND;
     dbms_output.put_line(‘CLERK à ‘ || M.ename);
 end loop;
 close cf;
open cf(‘MANAGER’);
LOOP
     FETCH CF INTO M;
     EXIT WHEN CF%NOTFOUND;
     dbms_output.put_line(‘MANAGER à ‘||M.ename);
 end loop;
 close cf;
END;
 
Cursor FOR UPDATE OF and CURRENT OF
    CURRENT OF clause is used in an UPDATE or DELETE statement to refer to the current row of the cursor
    The cursor must be declared with the FOR UPDATE OF clause and must be open and positioned on a row
    If the cursor is not open, CURRENT OF clause results in an error

8) Example of Cursor FOR UPDATE OF and CURRENT OF
 
create table esal
(empno number,
 sal number);
insert into esal
values(1,16000);
insert into esal
values(2,14000);
insert into esal
values(3,8000);
insert into esal
values(4,6500);
insert into esal
values(5,9000);
insert into esal
values(6,11000);
insert into esal
values(7,5500);
insert into esal
values(8,3500);
insert into esal
values(9,2200);
insert into esal
values(10,7000);
 
 
Multiple updations depending on the salary clause in one pl/sql block –
 
Declare
 Cursor cf is
 
 select * from esal;
 
 -- For Update of sal;
 
 M   cf%rowtype;
Begin
 Open cf;
 
  Loop
 
  Fetch cf into M;
 
  exit when cf%notfound;

 If M.Sal >= 16000 Then
         M.Sal := 20000;
  ElsIf M.Sal >= 14000 Then
         M.Sal := 18200;
  ElsIf M.Sal >= 12000 Then
         M.Sal := 16700;
  ElsIf M.Sal >= 10000 Then
         M.Sal := 13500;
  ElsIf M.Sal >= 8000 Then
         M.Sal := 11000;
        ElsIf M.Sal >= 6000 Then
         M.Sal := 9500;
  ElsIf M.Sal >= 4000 Then
         M.Sal := 7500;
  Else
         M.Sal := 5000;
        End If;
 
 Update esal
  set sal = M.Sal
     Where Current Of cf;
        End Loop;
 End;
 
 
Implicit Cursors
• Automatically defined and opened, by Oracle, to process each SQL statement
• most recently opened context area is referred to as a ‘SQL%’ cursor
 

Attributes of Implicit Cursors
 
Although OPEN, CLOSE and FETCH statements cannot be used to manipulate the SQL% cursor, the attributes can be used to access its context area
Attributes evaluate to NULL, before the cursor is opened automatically
The following four cursor attributes can be used to access the SQL% cursor’s context area
    SQL%NOTFOUND
    SQL%FOUND
    SQL%ROWCOUNT
    SQL%ISOPEN
    SQL%NOTFOUND
    evaluates to TRUE if an INSERT, UPDATE or DELETE statement affected no rows, else it evaluates to FALSE
    SQL%FOUND
    logical opposite of SQL%NOTFOUND
    evaluates to TRUE if an INSERT, UPDATE or DELETE affected one or more rows, else it evaluates to FALSE
 
    SQL%ROWCOUNT
        returns the number of rows affected by an INSERT, UPDATE or DELETE statement
    SQL%ISOPEN
        Oracle automatically closes an implicit cursor after executing its associated SQL statement
        For an implicit cursor SQL%ISOPEN always evaluates to FALSE
 
9) Example of Implicit Cursors
Begin
 
   Delete from emp
     where ename = '&name';
   If SQL%Found Then
        dbms_output.put_line('Record found and it is deleted');
   End If;

 If SQL%NotFound Then
 dbms_output.put_line('No record is present of the given name.');
 End If;
End;
 
 
10) Implicit Cursor for rowcount
 
Declare
C number := 0;
Begin
   Update Emp
     set sal = sal + 500
     where deptno = &deptno;
 
/*If no record is updated since the deptno supplied is wrong then giving
     the customised error message.*/
      If SQL%Rowcount = 0 then
         dbms_output.put_line('No records are updated since the department number entered is not in the table.');
     End if;
 
/*To prevent sal to be updated where deptno is > 3 */
       If SQL%RowCount > 3 then
         Rollback;
             dbms_output.put_line('Cannot update since there are more than 3 deptnos');
        End If;
 
        If SQL%RowCount Between 1 and 3 then
              c := SQL%RowCount;
              dbms_output.put_line(c || ' records updated.');
        End If;
End;
 

Discuss about Cursors

AuthorBody
Rahul
7/12/2009 6:56 AM
Please provide feedback about this article here.

To participate in this discussion Sign up for free membership of 24x7code.

To Signup click on Login , Use create user link & the follow the instructions.

Thank you.



Designed & Developed by Rahul Bagal