1 cursorscursors. 2 sql cursor a cursor is a private sql work area. a cursor is a private sql work...
TRANSCRIPT
1
CursorsCursorsCursorsCursors
2
SQL CursorSQL CursorSQL CursorSQL Cursor A cursor is a private SQL work A cursor is a private SQL work
area.area. There are two types of cursors:There are two types of cursors:
Implicit cursorsImplicit cursors Explicit cursorsExplicit cursors
The Oracle Server uses implicit The Oracle Server uses implicit cursors to parse and execute your cursors to parse and execute your SQL statements.SQL statements.
Explicit cursors are explicitly Explicit cursors are explicitly declared by the programmer.declared by the programmer.
A cursor is a private SQL work A cursor is a private SQL work area.area.
There are two types of cursors:There are two types of cursors: Implicit cursorsImplicit cursors Explicit cursorsExplicit cursors
The Oracle Server uses implicit The Oracle Server uses implicit cursors to parse and execute your cursors to parse and execute your SQL statements.SQL statements.
Explicit cursors are explicitly Explicit cursors are explicitly declared by the programmer.declared by the programmer.
3
CursorsCursors
Pointer to memory location on Pointer to memory location on database server database server DBMS uses to process a SQL queryDBMS uses to process a SQL query
Use to: Use to: Retrieve and manipulate database data Retrieve and manipulate database data
in PL/SQL programsin PL/SQL programs Types:Types:
ImplicitImplicit ExplicitExplicit
4
Cursor
Context Area
active setCID CALLID CNAME CCREDIT
1 MIS 101 Intro. to Info. Sy stems 3 2 MIS 301 Sy stems Analy sis 3 3 MIS 441 Database Management 3 4 CS 155 Programming in C++ 3 5 MIS 451 Client/Serv er Sy stems 3
Number of rows
processed
Parsed commandstatement
Database Server Memory
5
Implicit CursorsImplicit Cursors
Context areaContext area Contains information about queryContains information about query Created by INSERT, UPDATE, DELETE, Created by INSERT, UPDATE, DELETE,
or SELECTor SELECT Active setActive set
Set of data rows that query retrievesSet of data rows that query retrieves Implicit cursor Implicit cursor
Pointer to context areaPointer to context area
6
Implicit Cursors Implicit Cursors (continued)(continued)
Use to assign output of SELECT Use to assign output of SELECT query to PL/SQL program variables query to PL/SQL program variables When query will return only one recordWhen query will return only one record
7
Implicit Cursors Implicit Cursors (continued)(continued)
Useful to use %TYPE reference data Useful to use %TYPE reference data type type To declare variables used with implicit To declare variables used with implicit
cursorscursors Error “ORA-01422: exact fetch Error “ORA-01422: exact fetch
returns more than requested returns more than requested number of rows” number of rows” Implicit cursor query tried to retrieve Implicit cursor query tried to retrieve
multiple recordsmultiple records
8
SQL Cursor AttributesSQL Cursor AttributesSQL Cursor AttributesSQL Cursor Attributes
Using SQL cursor attributes, you Using SQL cursor attributes, you can test the outcome of your can test the outcome of your SQL statements. SQL statements.
Using SQL cursor attributes, you Using SQL cursor attributes, you can test the outcome of your can test the outcome of your SQL statements. SQL statements. SQL%ROWCOUNT Number of rows affected by the
most recent SQL statement (an integer value)
SQL%FOUND Boolean attribute that evaluates to TRUE if the most recent SQL statement affects one or more rows
SQL%NOTFOUND Boolean attribute that evaluates to TRUE if the most recent SQLstatement does not affect any rows
SQL%ISOPEN Always evaluates to FALSE because PL/SQL closes implicit cursorsimmediately after they are executed
9
SQL Cursor AttributesSQL Cursor AttributesSQL Cursor AttributesSQL Cursor Attributes Delete rows that have the Delete rows that have the
specified order number from the specified order number from the ITEM table. Print the number of ITEM table. Print the number of rows deleted.rows deleted.
ExampleExample
Delete rows that have the Delete rows that have the specified order number from the specified order number from the ITEM table. Print the number of ITEM table. Print the number of rows deleted.rows deleted.
ExampleExample VARIABLE rows_deleted VARCHAR2(30)DECLARE v_ordid NUMBER := 605;BEGIN DELETE FROM item WHERE ordid = v_ordid; :rows_deleted := (SQL%ROWCOUNT || ' rows deleted.');END;/PRINT rows_deleted
10
Implicit Cursor SQLImplicit Cursor SQL%ROWCOUNT Example%ROWCOUNT Example
SQL> SET SERVEROUTPUT ON;SQL> SET SERVEROUTPUT ON;SQL> DECLARESQL> DECLARE r NUMBER;r NUMBER; BEGINBEGIN DELETE FROM emp WHERE DELETE FROM emp WHERE
empno=7900;empno=7900; r:=SQL%ROWCOUNT;r:=SQL%ROWCOUNT; DBMS_OUTPUT.PUT_LINE(r);DBMS_OUTPUT.PUT_LINE(r); END;END; //11
11
Implicit Cursor SQLImplicit Cursor SQL%FOUND Example%FOUND Example
SQL> DECLARESQL> DECLARE r BOOLEAN;r BOOLEAN; BEGINBEGIN DELETE FROM emp WHERE empno=1000;DELETE FROM emp WHERE empno=1000; r:=SQL%FOUND;r:=SQL%FOUND; IF r THENIF r THEN DBMS_OUTPUT.PUT_LINE('Rows are founded');DBMS_OUTPUT.PUT_LINE('Rows are founded'); ELSEELSE DBMS_OUTPUT.PUT_LINE('No Rows are founded');DBMS_OUTPUT.PUT_LINE('No Rows are founded'); END IF;END IF; END;END; //No Rows are foundedNo Rows are founded
12
Implicit Cursor SQLImplicit Cursor SQL%ISOPEN Example%ISOPEN Example
SQL> DECLARESQL> DECLARE r BOOLEAN;r BOOLEAN; BEGINBEGIN UPDATE emp SET sal=1000 WHERE empno>7900;UPDATE emp SET sal=1000 WHERE empno>7900; r:=SQL%ISOPEN;r:=SQL%ISOPEN; IF r THEN IF r THEN DBMS_OUTPUT.PUT_LINE('The cursor is opened');DBMS_OUTPUT.PUT_LINE('The cursor is opened'); ELSEELSE DBMS_OUTPUT.PUT_LINE('The cursor is closed');DBMS_OUTPUT.PUT_LINE('The cursor is closed'); END IF;END IF; END;END; //The cursor is closedThe cursor is closed
13
About CursorsAbout CursorsAbout CursorsAbout Cursors
Every SQL statement Every SQL statement executed by the Oracle executed by the Oracle Server has an individual Server has an individual cursor associated with it:cursor associated with it: Implicit cursors: Declared for Implicit cursors: Declared for
all DML and PL/SQL SELECT all DML and PL/SQL SELECT statementsstatements
Explicit cursors: Declared and Explicit cursors: Declared and named by the programmernamed by the programmer
Every SQL statement Every SQL statement executed by the Oracle executed by the Oracle Server has an individual Server has an individual cursor associated with it:cursor associated with it: Implicit cursors: Declared for Implicit cursors: Declared for
all DML and PL/SQL SELECT all DML and PL/SQL SELECT statementsstatements
Explicit cursors: Declared and Explicit cursors: Declared and named by the programmernamed by the programmer
14
Explicit Cursor FunctionsExplicit Cursor FunctionsExplicit Cursor FunctionsExplicit Cursor Functions
Active setActive set
Current rowCurrent rowCursor
7369 SMITH CLERK
7566 JONES MANAGER
7788 SCOTT ANALYST
7876 ADAMS CLERK
7902 FORD ANALYST
15
Controlling Explicit Controlling Explicit CursorsCursors
Controlling Explicit Controlling Explicit CursorsCursors
• Create a Create a named named SQL areaSQL area
DECLAREDECLAREDECLAREDECLARE
• Identify Identify the active the active setset
OPENOPENOPENOPEN
• Load the Load the current current row into row into variablesvariables
FETCHFETCHFETCHFETCH
• Test for Test for existing existing rowsrows
EMPTY?
• Return to Return to FETCH if FETCH if rows rows foundfound
NoNo
• Release Release the active the active setset
CLOSECLOSECLOSECLOSEYesYes
16
Controlling Explicit Controlling Explicit CursorsCursors
Controlling Explicit Controlling Explicit CursorsCursorsOpen the cursor.Open the cursor.
CursorCursor
PointerPointer
Fetch a row from the cursor.Fetch a row from the cursor.
CursorCursor
PointerPointer
Continue until empty.Continue until empty.
CursorCursor
PointerPointer
Close the cursor.Close the cursor.
17
Declaring the CursorDeclaring the CursorDeclaring the CursorDeclaring the Cursor SyntaxSyntax
Do not include the INTO clause in the cursor Do not include the INTO clause in the cursor declaration.declaration.
If processing rows in a specific sequence is If processing rows in a specific sequence is required, use the ORDER BY clause in the query.required, use the ORDER BY clause in the query.
SyntaxSyntax
Do not include the INTO clause in the cursor Do not include the INTO clause in the cursor declaration.declaration.
If processing rows in a specific sequence is If processing rows in a specific sequence is required, use the ORDER BY clause in the query.required, use the ORDER BY clause in the query.
CURSOR cursor_name IS
select_statement;
CURSOR cursor_name IS
select_statement;
18
Declaring the CursorDeclaring the CursorDeclaring the CursorDeclaring the Cursor
ExampleExample ExampleExampleDECLARE CURSOR emp_cursor IS SELECT empno, ename FROM emp;
CURSOR dept_cursor IS SELECT * FROM dept WHERE deptno = 10;BEGIN ...
DECLARE CURSOR emp_cursor IS SELECT empno, ename FROM emp;
CURSOR dept_cursor IS SELECT * FROM dept WHERE deptno = 10;BEGIN ...
19
Opening the CursorOpening the CursorOpening the CursorOpening the Cursor
SyntaxSyntax
Open the cursor to execute the Open the cursor to execute the query and identify the active set.query and identify the active set.
If the query returns no rows, no If the query returns no rows, no exception is raised.exception is raised.
Use cursor attributes to test the Use cursor attributes to test the outcome after a fetch.outcome after a fetch.
SyntaxSyntax
Open the cursor to execute the Open the cursor to execute the query and identify the active set.query and identify the active set.
If the query returns no rows, no If the query returns no rows, no exception is raised.exception is raised.
Use cursor attributes to test the Use cursor attributes to test the outcome after a fetch.outcome after a fetch.
OPEN cursor_name;OPEN cursor_name;
20
Fetching Data from the Fetching Data from the CursorCursor
Fetching Data from the Fetching Data from the CursorCursor SyntaxSyntax
Retrieve the current row values into Retrieve the current row values into variables.variables.
Include the same number of variables.Include the same number of variables. Match each variable to correspond to the Match each variable to correspond to the
columns positionally.columns positionally. Test to see if the cursor contains rows.Test to see if the cursor contains rows.
The FETCH statement performs the The FETCH statement performs the following operations:following operations:
1. Advances the pointer to the next row in the 1. Advances the pointer to the next row in the active set.active set.
2. Reads the data for the current row into the 2. Reads the data for the current row into the output PL/SQL variables.output PL/SQL variables.
SyntaxSyntax
Retrieve the current row values into Retrieve the current row values into variables.variables.
Include the same number of variables.Include the same number of variables. Match each variable to correspond to the Match each variable to correspond to the
columns positionally.columns positionally. Test to see if the cursor contains rows.Test to see if the cursor contains rows.
The FETCH statement performs the The FETCH statement performs the following operations:following operations:
1. Advances the pointer to the next row in the 1. Advances the pointer to the next row in the active set.active set.
2. Reads the data for the current row into the 2. Reads the data for the current row into the output PL/SQL variables.output PL/SQL variables.
FETCH cursor_name INTO [variable1, variable2, ...]
| record_name];
FETCH cursor_name INTO [variable1, variable2, ...]
| record_name];
21
Fetching Data from the Fetching Data from the CursorCursor
Fetching Data from the Fetching Data from the CursorCursor
ExamplesExamples
ExamplesExamples
FETCH emp_cursor INTO v_empno, v_ename;FETCH emp_cursor INTO v_empno, v_ename;
...OPEN defined_cursor;LOOP FETCH defined_cursor INTO defined_variables EXIT WHEN ...; ... -- Process the retrieved data ...END;
...OPEN defined_cursor;LOOP FETCH defined_cursor INTO defined_variables EXIT WHEN ...; ... -- Process the retrieved data ...END;
22
Closing the CursorClosing the CursorClosing the CursorClosing the Cursor
SyntaxSyntax
Close the cursor after completing Close the cursor after completing the processing of the rows.the processing of the rows.
Reopen the cursor, if required.Reopen the cursor, if required. Do not attempt to fetch data from a Do not attempt to fetch data from a
cursor once it has been closed.cursor once it has been closed. The CLOSE statement releases the context The CLOSE statement releases the context
area.area.
SyntaxSyntax
Close the cursor after completing Close the cursor after completing the processing of the rows.the processing of the rows.
Reopen the cursor, if required.Reopen the cursor, if required. Do not attempt to fetch data from a Do not attempt to fetch data from a
cursor once it has been closed.cursor once it has been closed. The CLOSE statement releases the context The CLOSE statement releases the context
area.area.
CLOSE cursor_name;CLOSE cursor_name;
23
Explicit Cursor ExampleExplicit Cursor ExampleSQL> DECLARESQL> DECLARE v_num emp.empno%TYPE;v_num emp.empno%TYPE; v_name emp.ename%TYPE;v_name emp.ename%TYPE; CURSOR my_cursor IS SELECT empno,ename FROM emp CURSOR my_cursor IS SELECT empno,ename FROM emp
WHERE empno>7900;WHERE empno>7900; BEGINBEGIN OPEN my_cursor;OPEN my_cursor; LOOPLOOP FETCH my_cursor INTO v_num,v_name;FETCH my_cursor INTO v_num,v_name; EXIT WHEN my_cursor%NOTFOUND;EXIT WHEN my_cursor%NOTFOUND; DBMS_OUTPUT.PUT_LINE(v_num || ' has the name ' ||v_name);DBMS_OUTPUT.PUT_LINE(v_num || ' has the name ' ||v_name); END LOOP;END LOOP; CLOSE my_cursor;CLOSE my_cursor; END;END; //7902 has the name FORD7902 has the name FORD7934 has the name MILLER7934 has the name MILLER
24
Explicit Cursor Explicit Cursor AttributesAttributes
Explicit Cursor Explicit Cursor AttributesAttributes Obtain status information about Obtain status information about
a cursor.a cursor.
Obtain status information about Obtain status information about a cursor.a cursor.Attribute Type Description
%ISOPEN Boolean Evaluates to TRUE if the cursor is open
%NOTFOUND Boolean Evaluates to TRUE if the most recent fetch does not return a row
%FOUND Boolean Evaluates to TRUE if the mostrecent fetch returns a row; complement of %NOTFOUND
%ROWCOUNT Number Evaluates to the total number of rows returned so far
25
Controlling Multiple Controlling Multiple FetchesFetches
Controlling Multiple Controlling Multiple FetchesFetches
Process several rows from an Process several rows from an explicit cursor using a loop.explicit cursor using a loop.
Fetch a row with each iteration.Fetch a row with each iteration. Use the %NOTFOUND attribute to Use the %NOTFOUND attribute to
write a test for an unsuccessful write a test for an unsuccessful fetch.fetch.
Use explicit cursor attributes to Use explicit cursor attributes to test the success of each fetch.test the success of each fetch.
Process several rows from an Process several rows from an explicit cursor using a loop.explicit cursor using a loop.
Fetch a row with each iteration.Fetch a row with each iteration. Use the %NOTFOUND attribute to Use the %NOTFOUND attribute to
write a test for an unsuccessful write a test for an unsuccessful fetch.fetch.
Use explicit cursor attributes to Use explicit cursor attributes to test the success of each fetch.test the success of each fetch.
26
The %ISOPEN AttributeThe %ISOPEN AttributeThe %ISOPEN AttributeThe %ISOPEN Attribute Fetch rows only when the cursor is Fetch rows only when the cursor is
open. open. Use the %ISOPEN cursor attribute Use the %ISOPEN cursor attribute
before performing a fetch to test before performing a fetch to test whether the cursor is open.whether the cursor is open.
ExampleExample
Fetch rows only when the cursor is Fetch rows only when the cursor is open. open.
Use the %ISOPEN cursor attribute Use the %ISOPEN cursor attribute before performing a fetch to test before performing a fetch to test whether the cursor is open.whether the cursor is open.
ExampleExampleIF NOT emp_cursor%ISOPEN THEN
OPEN emp_cursor;END IF;LOOP FETCH emp_cursor...
IF NOT emp_cursor%ISOPEN THENOPEN emp_cursor;
END IF;LOOP FETCH emp_cursor...
27
The %NOTFOUND The %NOTFOUND and %ROWCOUNT and %ROWCOUNT
AttributesAttributes
The %NOTFOUND The %NOTFOUND and %ROWCOUNT and %ROWCOUNT
AttributesAttributes Use the %ROWCOUNT cursor Use the %ROWCOUNT cursor
attribute to retrieve an exact attribute to retrieve an exact number of rows.number of rows.
The value of %ROWCOUNT before The value of %ROWCOUNT before fetching any row is NULL.fetching any row is NULL.
Use the %NOTFOUND cursor Use the %NOTFOUND cursor attribute to determine when to exit attribute to determine when to exit the loop.the loop.
Use the %ROWCOUNT cursor Use the %ROWCOUNT cursor attribute to retrieve an exact attribute to retrieve an exact number of rows.number of rows.
The value of %ROWCOUNT before The value of %ROWCOUNT before fetching any row is NULL.fetching any row is NULL.
Use the %NOTFOUND cursor Use the %NOTFOUND cursor attribute to determine when to exit attribute to determine when to exit the loop.the loop.
28
Explicit Cursor %ISOPEN Explicit Cursor %ISOPEN ExampleExample
SQL> DECLARESQL> DECLARE v_num emp.empno%TYPE;v_num emp.empno%TYPE; v_name emp.ename%TYPE;v_name emp.ename%TYPE; r BOOLEAN;r BOOLEAN; CURSOR my_cursor IS SELECT empno,ename FROM emp WHERE CURSOR my_cursor IS SELECT empno,ename FROM emp WHERE
empno>7900;empno>7900; BEGINBEGIN OPEN my_cursor;OPEN my_cursor; r:=my_cursor%ISOPEN;r:=my_cursor%ISOPEN; IF r THEN IF r THEN DBMS_OUTPUT.PUT_LINE('The Cursor is opened after the open DBMS_OUTPUT.PUT_LINE('The Cursor is opened after the open
statement');statement'); ELSEELSE DBMS_OUTPUT.PUT_LINE('The Cursor is closed after the open DBMS_OUTPUT.PUT_LINE('The Cursor is closed after the open
statement');statement'); END IF;END IF;
29
Explicit Cursor %ISOPEN Explicit Cursor %ISOPEN Example Cont.Example Cont.
LOOPLOOP FETCH my_cursor INTO v_num,v_name;FETCH my_cursor INTO v_num,v_name; EXIT WHEN my_cursor%NOTFOUND;EXIT WHEN my_cursor%NOTFOUND; END LOOP;END LOOP; CLOSE my_cursor;CLOSE my_cursor; r:=my_cursor%ISOPEN;r:=my_cursor%ISOPEN; IF r THEN IF r THEN DBMS_OUTPUT.PUT_LINE('The Cursor is opened after the close DBMS_OUTPUT.PUT_LINE('The Cursor is opened after the close
statement');statement'); ELSEELSE DBMS_OUTPUT.PUT_LINE('The Cursor is closed after the close DBMS_OUTPUT.PUT_LINE('The Cursor is closed after the close
statement');statement'); END IF;END IF; END;END; //The Cursor is opened after the open statementThe Cursor is opened after the open statementThe Cursor is closed after the close statementThe Cursor is closed after the close statement
30
Explicit Cursor Explicit Cursor %ROWCOUNT Example%ROWCOUNT Example
SQL> DECLARESQL> DECLARE v_name emp.ename%TYPE;v_name emp.ename%TYPE; r NUMBER;r NUMBER; c NUMBER:=1;c NUMBER:=1; CURSOR my_cursor IS SELECT ename FROM emp WHERE empno>7900;CURSOR my_cursor IS SELECT ename FROM emp WHERE empno>7900; BEGINBEGIN OPEN my_cursor;OPEN my_cursor; LOOPLOOP FETCH my_cursor INTO v_name;FETCH my_cursor INTO v_name; EXIT WHEN my_cursor%NOTFOUND;EXIT WHEN my_cursor%NOTFOUND; r:=my_cursor%ROWCOUNT;r:=my_cursor%ROWCOUNT; DBMS_OUTPUT.PUT_LINE('After fetch number ' || c || ' ROWCOUNT has the value ' || DBMS_OUTPUT.PUT_LINE('After fetch number ' || c || ' ROWCOUNT has the value ' ||
r);r); c:=c+1;c:=c+1; END LOOP;END LOOP; CLOSE my_cursor;CLOSE my_cursor; END;END; //After fetch number 1 ROWCOUNT has the value 1After fetch number 1 ROWCOUNT has the value 1After fetch number 2 ROWCOUNT has the value 2After fetch number 2 ROWCOUNT has the value 2
31
Cursors and RecordsCursors and RecordsCursors and RecordsCursors and Records Process the rows of the active Process the rows of the active
set conveniently by fetching set conveniently by fetching values into a PL/SQL RECORD.values into a PL/SQL RECORD.
ExampleExample
Process the rows of the active Process the rows of the active set conveniently by fetching set conveniently by fetching values into a PL/SQL RECORD.values into a PL/SQL RECORD.
ExampleExampleDECLARE CURSOR emp_cursor IS SELECT empno, ename FROM emp; emp_record emp_cursor%ROWTYPE;BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO emp_record; ...
DECLARE CURSOR emp_cursor IS SELECT empno, ename FROM emp; emp_record emp_cursor%ROWTYPE;BEGIN OPEN emp_cursor; LOOP FETCH emp_cursor INTO emp_record; ...
32
SyntaxSyntax
The cursor FOR loop is a shortcut to The cursor FOR loop is a shortcut to process explicit cursors.process explicit cursors.
Implicit open, fetch, and close occur.Implicit open, fetch, and close occur. The record is implicitly declared.The record is implicitly declared.
SyntaxSyntax
The cursor FOR loop is a shortcut to The cursor FOR loop is a shortcut to process explicit cursors.process explicit cursors.
Implicit open, fetch, and close occur.Implicit open, fetch, and close occur. The record is implicitly declared.The record is implicitly declared.
Cursor FOR LoopsCursor FOR LoopsCursor FOR LoopsCursor FOR Loops
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
FOR record_name IN cursor_name LOOP
statement1;
statement2;
. . .
END LOOP;
33
Cursor FOR LoopsCursor FOR LoopsCursor FOR LoopsCursor FOR Loops
Retrieve employees one by one Retrieve employees one by one until no more are left.until no more are left.
ExampleExample
Retrieve employees one by one Retrieve employees one by one until no more are left.until no more are left.
ExampleExampleDECLARE CURSOR emp_cursor IS SELECT ename, deptno FROM emp;BEGIN FOR emp_record IN emp_cursor LOOP -- implicit open and implicit fetch occur IF emp_record.deptno = 30 THEN ... END LOOP; -- implicit close occursEND;
DECLARE CURSOR emp_cursor IS SELECT ename, deptno FROM emp;BEGIN FOR emp_record IN emp_cursor LOOP -- implicit open and implicit fetch occur IF emp_record.deptno = 30 THEN ... END LOOP; -- implicit close occursEND;
SummarySummarySummarySummary Cursor types:Cursor types:
Implicit cursors: Used for all DML Implicit cursors: Used for all DML statements and single-row queries.statements and single-row queries.
Explicit cursors: Used for queries of Explicit cursors: Used for queries of zero, one, or more rows.zero, one, or more rows.
You can manipulate explicit cursors.You can manipulate explicit cursors. You can evaluate the cursor status You can evaluate the cursor status
by using cursor attributes.by using cursor attributes. You can use cursor FOR loops.You can use cursor FOR loops.
Cursor types:Cursor types: Implicit cursors: Used for all DML Implicit cursors: Used for all DML
statements and single-row queries.statements and single-row queries. Explicit cursors: Used for queries of Explicit cursors: Used for queries of
zero, one, or more rows.zero, one, or more rows. You can manipulate explicit cursors.You can manipulate explicit cursors. You can evaluate the cursor status You can evaluate the cursor status
by using cursor attributes.by using cursor attributes. You can use cursor FOR loops.You can use cursor FOR loops.