What are Cursors?
A cursor is a temporary
work area created in the system memory when a SQL statement is executed. A
cursor contains information on a select statement and the rows of data accessed
by it.
This temporary work area
is used to store the data retrieved from the database, and manipulate this
data. A cursor can hold more than one row, but can process only one row at a
time. The set of rows the cursor holds is called the active set.
There are two types of
cursors in PL/SQL:
Implicit
cursors
These are created by
default when DML statements like, INSERT, UPDATE, and DELETE statements are
executed. They are also created when a SELECT statement that returns just one
row is executed.
Explicit
cursors
They must be created when
you are executing a SELECT statement that returns more than one row. Even
though the cursor stores multiple records, only one record can be processed at
a time, which is called as current row. When you fetch a row the current row position
moves to next row.
Both implicit and
explicit cursors have the same functionality, but they differ in the way they
are accessed.
Implicit Cursors:
Application
When you execute DML
statements like DELETE, INSERT, UPDATE and SELECT statements, implicit
statements are created to process these statements.
Oracle provides few
attributes called as implicit cursor attributes to check the status of DML
operations. The cursor attributes available are %FOUND, %NOTFOUND, %ROWCOUNT,
and %ISOPEN.
For example, When you
execute INSERT, UPDATE, or DELETE statements the cursor attributes tell us
whether any rows are affected and how many have been affected.
When a SELECT... INTO statement is executed in a PL/SQL Block, implicit cursor attributes can be used to find out whether any row has been returned by the SELECT statement. PL/SQL returns an error when no data is selected.
When a SELECT... INTO statement is executed in a PL/SQL Block, implicit cursor attributes can be used to find out whether any row has been returned by the SELECT statement. PL/SQL returns an error when no data is selected.
The status of the cursor
for each of these attributes are defined in the below table.
Attributes
|
Return
Value
|
Example
|
%FOUND
|
The return value is TRUE, if the DML statements like INSERT,
DELETE and UPDATE affect at least one row and if SELECT ….INTO statement
return at least one row.
|
SQL%FOUND
|
The return value is FALSE, if DML statements like INSERT,
DELETE and UPDATE do not affect row and if SELECT….INTO statement do not
return a row.
|
||
%NOTFOUND
|
The return value is FALSE, if DML statements like INSERT,
DELETE and UPDATE at least one row and if SELECT ….INTO statement return at
least one row.
|
SQL%NOTFOUND
|
The return value is TRUE, if a DML statement like INSERT,
DELETE and UPDATE do not affect even one row and if SELECT ….INTO statement
does not return a row.
|
||
%ROWCOUNT
|
Return the number of rows affected by the DML operations
INSERT, DELETE, UPDATE, SELECT
|
SQL%ROWCOUNT
|
For Example: Consider the
PL/SQL Block that uses implicit cursor attributes as shown below:
DECLARE var_rows number(5);
BEGIN
UPDATE employee
SET salary = salary + 1000;
IF SQL%NOTFOUND THEN
dbms_output.put_line('None of the salaries
where updated');
ELSIF SQL%FOUND THEN
var_rows := SQL%ROWCOUNT;
dbms_output.put_line('Salaries for ' ||
var_rows || 'employees are updated');
END IF;
END;
In the above PL/SQL
Block, the salaries of all the employees in the ‘employee’ table are updated.
If none of the employee’s salary are updated we get a message 'None of the
salaries where updated'. Else we get a message like for example, 'Salaries for
1000 employees are updated' if there are 1000 rows in ‘employee’ table.
Explicit Cursors
An explicit cursor is defined in the
declaration section of the PL/SQL Block. It is created on a SELECT Statement
which returns more than one row. We can provide a suitable name for the cursor.
General Syntax for
creating a cursor is as given below:
CURSOR cursor_name IS
select_statement;
- cursor_name
– A suitable name for the cursor.
- select_statement
– A select query which returns multiple rows.
How to
use Explicit Cursor?
There are four steps in
using an Explicit Cursor.
|
1) Declaring a Cursor in
the Declaration Section:
DECLARE
CURSOR emp_cur IS
SELECT *
FROM emp_tbl
WHERE salary > 5000;
In
the above example we are creating a cursor ‘emp_cur’ on a query which returns
the records of all the
employees with salary greater than 5000. Here ‘emp_tbl’ in the table which contains records of all the
employees.
employees with salary greater than 5000. Here ‘emp_tbl’ in the table which contains records of all the
employees.
2) Accessing the records
in the cursor:
Once the cursor is created in the declaration section we can access the cursor in the execution
section of the PL/SQL program.
Once the cursor is created in the declaration section we can access the cursor in the execution
section of the PL/SQL program.
How to
access an Explicit Cursor?
These are the three steps in accessing the
cursor.
1) Open the cursor.
2) Fetch the records in the cursor one at a time.
3) Close the cursor.
1) Open the cursor.
2) Fetch the records in the cursor one at a time.
3) Close the cursor.
General Syntax to open a
cursor is:
OPEN cursor_name;
General Syntax to fetch
records from a cursor is:
FETCH cursor_name INTO
record_name;
OR
FETCH cursor_name INTO
variable_list;
General Syntax to close a
cursor is:
CLOSE cursor_name;
When a cursor is opened,
the first row becomes the current row. When the data is fetched it is copied to
the record or variables and the logical pointer moves to the next row and it
becomes the current row. On every fetch statement, the pointer moves to the
next row. If you want to fetch after the last row, the program will throw an
error. When there is more than one row in a cursor we can use loops along with
explicit cursor attributes to fetch all the records.
Points to remember while
fetching a row:
· We can fetch the rows
in a cursor to a PL/SQL Record or a list of variables created in the PL/SQL
Block.
· If you are fetching a cursor to a PL/SQL Record, the record should have the same structure as the cursor.
· If you are fetching a cursor to a list of variables, the variables should be listed in the same order in the fetch statement as the columns are present in the cursor.
· If you are fetching a cursor to a PL/SQL Record, the record should have the same structure as the cursor.
· If you are fetching a cursor to a list of variables, the variables should be listed in the same order in the fetch statement as the columns are present in the cursor.
General Form of using an
explicit cursor is:
DECLARE
variables;
records;
create a cursor;
BEGIN
OPEN cursor;
FETCH cursor;
process the records;
CLOSE cursor;
END;
Explicit
Cursor, Lets Look at the example below
Example 1:
1> DECLARE
2> emp_rec emp_tbl%rowtype;
3> CURSOR emp_cur IS
4> SELECT *
5> FROM
6> WHERE salary > 10;
7> BEGIN
8> OPEN emp_cur;
9> FETCH emp_cur INTO emp_rec;
10> dbms_output.put_line (emp_rec.first_name ||
' ' || emp_rec.last_name);
11> CLOSE emp_cur;
12> END;
In the above example,
first we are creating a record ‘emp_rec’ of the same structure as of table
‘emp_tbl’ in line no 2. We can also create a record with a cursor by replacing
the table name with the cursor name. Second, we are declaring a cursor
‘emp_cur’ from a select query in line no 3 - 6. Third, we are opening the
cursor in the execution section in line no 8. Fourth, we are fetching the
cursor to the record in line no 9. Fifth, we are displaying the first_name and
last_name of the employee in the record emp_rec in line no 10. Sixth, we are
closing the cursor in line no 11.
What are Explicit Cursor
Attributes?
Oracle provides some
attributes known as Explicit Cursor Attributes to control the data processing
while using cursors. We use these attributes to avoid errors while accessing
cursors through OPEN, FETCH and CLOSE Statements.
When does an error occur
while accessing an explicit cursor?
a) When we try to open a
cursor which is not closed in the previous operation.
b) When we try to fetch a cursor after the last operation.
b) When we try to fetch a cursor after the last operation.
These are the attributes
available to check the status of an explicit cursor.
Attributes
|
Return
values
|
Example
|
%FOUND
|
TRUE, if fetch statement returns at least one row.
|
Cursor_name%FOUND
|
FALSE, if fetch statement doesn’t return a row.
|
||
%NOTFOUND
|
TRUE, , if fetch statement doesn’t return a row.
|
Cursor_name%NOTFOUND
|
FALSE, if fetch statement returns at least one row.
|
||
%ROWCOUNT
|
The number of rows fetched by the fetch statement
|
Cursor_name%ROWCOUNT
|
If no row is returned, the PL/SQL statement returns an error.
|
||
%ISOPEN
|
TRUE, if the cursor is already open in the program
|
Cursor_name%ISNAME
|
FALSE, if the cursor is not opened in the program.
|
Using Loops with Explicit
Cursors:
Oracle provides three
types of cursors namely SIMPLE LOOP, WHILE LOOP and FOR LOOP. These loops can
be used to process multiple rows in the cursor. Here I will modify the same
example for each loops to explain how to use loops with cursors.
Cursor
with a Simple Loop:
1> DECLARE
2> CURSOR emp_cur IS
3> SELECT first_name, last_name, salary FROM
emp_tbl;
4> emp_rec emp_cur%rowtype;
5> BEGIN
6> IF NOT sales_cur%ISOPEN THEN
7> OPEN sales_cur;
8> END IF;
9> LOOP
10> FETCH emp_cur INTO emp_rec;
11> EXIT WHEN emp_cur%NOTFOUND;
12> dbms_output.put_line(emp_cur.first_name ||
' ' ||emp_cur.last_name
13> || ' ' ||emp_cur.salary);
14> END LOOP;
15> END;
16> /
In the above example we
are using two cursor attributes %ISOPEN and %NOTFOUND.
In line no 6, we are using the cursor attribute %ISOPEN to check if the cursor is open, if the condition is true the program does not open the cursor again, it directly moves to line no 9.
In line no 11, we are using the cursor attribute %NOTFOUND to check whether the fetch returned any row. If there is no rows found the program would exit, a condition which exists when you fetch the cursor after the last row, if there is a row found the program continues.
In line no 6, we are using the cursor attribute %ISOPEN to check if the cursor is open, if the condition is true the program does not open the cursor again, it directly moves to line no 9.
In line no 11, we are using the cursor attribute %NOTFOUND to check whether the fetch returned any row. If there is no rows found the program would exit, a condition which exists when you fetch the cursor after the last row, if there is a row found the program continues.
We can use %FOUND in
place of %NOTFOUND and vice versa. If we do so, we need to reverse the logic of
the program. So use these attributes in appropriate instances.
Cursor
with a While Loop:
Lets modify the above
program to use while loop.
1> DECLARE
2> CURSOR emp_cur IS
3> SELECT first_name, last_name, salary FROM
emp_tbl;
4> emp_rec emp_cur%rowtype;
5> BEGIN
6> IF NOT sales_cur%ISOPEN THEN
7> OPEN sales_cur;
8> END IF;
9> FETCH sales_cur INTO sales_rec;
10> WHILE sales_cur%FOUND THEN
11> LOOP
12> dbms_output.put_line(emp_cur.first_name ||
' ' ||emp_cur.last_name
13> || ' ' ||emp_cur.salary);
15> FETCH sales_cur INTO sales_rec;
16> END LOOP;
17> END;
18> /
In the above example, in
line no 10 we are using %FOUND to evaluate if the first fetch statement in line
no 9 returned a row, if true the program moves into the while loop. In the loop
we use fetch statement again (line no 15) to process the next row. If the fetch
statement is not executed once before the while loop the while condition will
return false in the first instance and the while loop is skipped. In the loop,
before fetching the record again, always process the record retrieved by the
first fetch statement, else you will skip the first row.
Cursor
with a FOR Loop:
When using FOR LOOP you
need not declare a record or variables to store the cursor values, need not
open, fetch and close the cursor. These functions are accomplished by the FOR
LOOP automatically.
General
Syntax for using FOR LOOP:
FOR record_name IN
cusror_name
LOOP
process the row...
END LOOP;
Let’s use the above
example to learn how to use for loops in cursors.
1> DECLARE
2> CURSOR emp_cur IS
3> SELECT first_name, last_name, salary FROM
emp_tbl;
4> emp_rec emp_cur%rowtype;
5> BEGIN
6> FOR emp_rec in sales_cur
7> LOOP
8> dbms_output.put_line(emp_cur.first_name || '
' ||emp_cur.last_name
9> || ' ' ||emp_cur.salary);
10> END LOOP;
11>END;
12> /
In the above example,
when the FOR loop is processed a record ‘emp_rec’of structure ‘emp_cur’ gets
created, the cursor is opened, the rows are fetched to the record ‘emp_rec’ and
the cursor is closed after the last row is processed. By using FOR Loop in your
program, you can reduce the number of lines in the program.
NOTE: In the
examples given above, we are using backward slash ‘/’ at the end of the
program. This indicates the oracle engine that the PL/SQL program has ended and
it can begin processing the statements.
No comments:
Post a Comment