CURSORS
is the way you loop through the rows returned by a Select statement. Say for example from SQL* Plus if you write SELECT customer_name FROM customer returns the set of rows from customer table. If your corporation decides to give some discounts for your customers, based on how loyal he is, how much business we do with that customer etc etc, now we need to check some of the stuff before giving discounts, so we need to check one by one row from customer table and make a decision based on the rules. So here we cannot use a single update statement to the related tables. Now Cursor comes into picture. A cursor is nothing but a result set through which you can fetch one by one row.
They are two different types of cursors
Implicit cursors is nothing but if you issue a select statement the server executes the query
and stores the rows in a memory area in the server and returns the rows in network packets to
the server, here you do not have the control in the result set of rows.
Explicit cursors is the sql statements where you have the control over the result set
where you can fetch one by one row from the result set.
Things should be done while dealing with cursors
Declare a cursor
Open a cursor
Fetch data into variables from the cursor
Close the cursor
Following picture will give you some idea about the cursor.
Remember while working with cursors
we must provide same number of variables as the number of columns we selected in the
select statement of the cursor.
You cannot fetch once you closed the cursor, if you do it will raise an exception called
invalid_cursor. You can do fetch only after opening the cursor.
Cursor Attributes
%ISOPEN returns TRUE if already the cursor is open. returns FALSE if its not opened.
%NOTFOUND returns TRUE if the last fetch statement does not return a row.
%FOUND returns TRUE if the last fetch statement return a row.
%ROWCOUNT total number of rows returned so far.
How you declare a Cursor?
This can be done in the DECLARE section of a PL/SQL Block.
DECLARE
var_custname customer.cust_name%type;
CURSOR getcustnames IS SELECT cust_name FROM customer;
BEGIN
OPEN getcustnames; --opening a
cursor, actually execute the sql
--and places all the rows in server memory area
LOOP
FETCH getcustnames into var_custname; -- Fetching the current record
Exit When getcustnames%NOTFOUND --If all the rows got over then
--
%NOTFOUND cursor attribute will be true.
dbms_output.put_line(var_custname); -- Display the customer name
END LOOP;
Close getcustnames; -- Close the cursor so that server releases memory.
END;
Passing Arguments to a cursor
DECLARE
TYPE id_emp_table IS TABLE OF number(2)
INDEX BY BINARY_INTEGER;
v_deptno number(2);
i BINARY_INTEGER := 1;
CURSOR get_empno(v_in_dept number(2))
IS SELECT empno FROM emp where deptno = v_in_dept;
empno_plsql_table id_emp_table;
BEGIN
v_deptno := 30;
Open c1(v_deptno);
Loop
Fetch c1 into v_empno_hold;
If c1%FOUND then
empno_plsql_table(i) := v_empno_hold;
i := i + 1;
Else
Exit;
End If;
End Loop;
Close c1;
For j in 1..i Loop
dbms_output.put_line( empno_plsql_table(j) );
End Loop;
END;
FOR UPDATE cursor
DECLARE
v_deptno number(3);
CURSOR c1 IS select empno, deptno from emp FOR UPDATE;
BEGIN
For c1_record IN c1 Loop
If deptno = 40 then
DELETE from emp WHERE CURRENT OF c1;
End If;
End Loop;
COMMIT WORK;
END;