Cursors in PL-SQL
Cursors in PL-SQL
Cursors in PL-SQL
Oracle creates a memory area, known as the context area, for processing an SQL statement,
which contains all the information needed for processing the statement; for example, the
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 and explicit cursors.
Implicit cursors
Whenever Oracle executes an SQL statement such as SELECT INTO, INSERT, UPDATE,
and DELETE, it automatically creates an implicit cursor.
These cursors cannot be named and, hence they cannot be controlled or referred from another
place of the code. We can refer only to the most recent cursor through the cursor attributes.
Both Implicit cursor and the explicit cursor has certain attributes that can be accessed. These
attributes give more information about the cursor operations. Below are the different cursor
attributes and their usage.
The following table provides the description of the most used attributes −
%FOUND
1 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
2 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
3 Always returns FALSE for implicit cursors, because Oracle closes the SQL cursor
automatically after executing its associated SQL statement.
%ROWCOUNT
4 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.
Example
We will be using the CUSTOMERS table we had created and used in the previous chapters.
Select * from customers;
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2000.00 |
| 2 | Khilan | 25 | Delhi | 1500.00 |
| 3 | kaushik | 23 | Kota | 2000.00 |
| 4 | Chaitali | 25 | Mumbai | 6500.00 |
| 5 | Hardik | 27 | Bhopal | 8500.00 |
| 6 | Komal | 22 | MP | 4500.00 |
+----+----------+-----+-----------+----------+
The following program will update the table and increase the salary of each customer by 500
and use the SQL%ROWCOUNT attribute to determine the number of rows affected −
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
SET salary = salary + 500;
IF sql%notfound THEN
dbms_output.put_line('no customers selected');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' customers selected ');
END IF;
OR
IF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' Records Update ');
ELSIF
dbms_output.put_line('no customers selected');
END IF;
END;
/
When the above code is executed at the SQL prompt, it produces the following result −
6 customers selected
PL/SQL procedure successfully completed.
DECLARE
total_rows number(2);
BEGIN
UPDATE customers
SET salary = salary + 500
where ID Between 1 and 5;
OR
UPDATE customers
SET salary = salary + 500
where ID <=5;
IF sql%notfound THEN
dbms_output.put_line('no customers selected');
ELSIF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' customers selected ');
END IF;
OR
IF sql%found THEN
total_rows := sql%rowcount;
dbms_output.put_line( total_rows || ' Records Update ');
ELSIF
dbms_output.put_line('no customers selected');
END IF;
END;
/
If you check the records in customers table, you will find that the rows have been updated −
Select * from customers;
+----+----------+-----+-----------+----------+
| ID | NAME | AGE | ADDRESS | SALARY |
+----+----------+-----+-----------+----------+
| 1 | Ramesh | 32 | Ahmedabad | 2500.00 |
| 2 | Khilan | 25 | Delhi | 2000.00 |
| 3 | kaushik | 23 | Kota | 2500.00 |
| 4 | Chaitali | 25 | Mumbai | 7000.00 |
| 5 | Hardik | 27 | Bhopal | 9000.00 |
| 6 | Komal | 22 | MP | 5000.00 |
+----+----------+-----+-----------+----------+
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.
Working with an explicit cursor includes the following steps −
Declaring the cursor for initializing the memory
Opening the cursor for allocating the memory
Fetching the cursor for retrieving the data
Closing the cursor to release the allocated memory
Opening Cursor
Opening the cursor will instruct the PL/SQL to allocate the memory for this cursor. It will
make the cursor ready to fetch the records.
Each fetch statement will fetch one active set and holds the information of that particular
record. This statement is same as 'SELECT' statement that fetches the record and assigns
to the variable in the 'INTO' clause, but it will not throw any exceptions.
DECLARE
<cursor_variable declaration>
BEGIN
OPEN <cursor_name>;
END;
In the above syntax, the declaration part contains the declaration of the cursor and the
cursor variable in which the fetched data will be assigned.
The cursor is created for the 'SELECT' statement that is given in the cursor declaration.
In execution part, the declared cursor is opened, fetched and closed.
Example :
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 allocates the memory for the cursor and makes it ready for fetching the rows
returned by the SQL statement into it. For example, we will open the above defined cursor as
follows −
OPEN c_customers;
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 the
above-opened cursor as follows −
CLOSE c_customers;
c_id customers.id%type;
c_name customers.name%type;
c_addr customers.address%type;
BEGIN
LOOP
FETCH c_customers into c_id, c_name, c_addr; ‘Fetching the data from Cursor
END LOOP;
END;
/
Display Records from Wholesaler Table Using Cursor :
DECLARE
wno wholesaler.w_no%type;
wname wholesaler.w_name%type;
wadd wholesaler.address%type;
wcity wholesaler.city%type;
BEGIN
LOOP
FETCH c_wholesaler into wno, wname, wadd, wcity; ‘Fetching Data from Cursor
dbms_output.put_line(wno || ' ' || wname || ' ' || wadd|| ' ' || wcity);
END LOOP;
END;
An explicit cursor may accept a list of parameters. Each time you open the cursor, you can pass
different arguments to the cursor, which results in different result sets.
Example :
Cursor display employee information from emp_information table whose eid is four (4).
DECLARE
cursor c(no number) is select * from emp ‘Declaring Cursor
where eid = no;
temp emp%rowtype;
BEGIN
OPEN c(4); ‘Open the Cursor
LOOP
FETCH c INTO temp; ‘Fetch Data from Cursor
EXIT WHEN c%NOTFOUND;
dbms_output.put_line('EMP_No: '||temp.eid);
dbms_output.put_line('EMP_Name: '||temp.ename);
dbms_output.put_line('EMP_Salary:'||temp.esal);
END LOOP;
/*OR Use the following LOOP
FOR temp IN c(4) LOOP
dbms_output.put_line('EMP_No: '||temp.eid);
dbms_output.put_line('EMP_Name: '||temp.ename);
dbms_output.put_line('EMP_Salary:'||temp.esal);
END Loop;*/
CLOSE c; ‘Close the Cursor
END;
/
DECLARE
erec emp%rowtype;
BEGIN
OPEN c1;
LOOP
IF c1%rowcount<=4 THEN
END IF;
END LOOP;
END;
Output :
4 aparna 50000
5 vishal 45000
1 sumit 20000
3 akash 14000
Create a procedure to Display records of employee of first four highest paid employees :
as
erec emp%rowtype;
BEGIN
OPEN c1;
LOOP
IF c1%rowcount<=4 THEN
END IF;
END LOOP;
END;
Procedure created.
4 aparna 50000
5 vishal 45000
1 sumit 20000
3 akash 14000