When to Use a Cursor | Programming With Cursors |
A Cursor Example | Declaring The Cursor |
Opening The Cursor | Fetching Rows |
Closing The Cursor | Freeing The Cursor |
Updating And Deleting Rows |
Despite the convenience of the the multi-row SELECT, there are numerous occasions where the use of a cursor is warranted, and even necessary:
This process is often referred to as a "FETCH loop".
A Cursor Example
The following program demonstrates how cursors are used:
/* REXX */ address sql /* Declare variables */ "exec sql begin declare section;" "exec sql declare ln variable varchar(15);" "exec sql declare sal variable decimal(9,2);" "exec sql end declare section;" /* Associate a SELECT statement with a cursor name */ "exec sql declare empcsr cursor for", "select lastname, salary", "from dsn8230.emp", "where lastname like 'H%';" /* Open the cursor - DB2 creates a result table */ "exec sql open empcsr;" if rc<>0 then exit /* Loop through the rows of the result table */ "exec sql fetch empcsr into :ln, :sal;" do while rc=0 say ln sal "exec sql fetch empcsr into :ln, :sal;" end /* Close the cursor - DB2 throws away the result table */ "exec sql close empcsr;" /* Free the cursor's data structure */ "exec sql free empcsr cursor;"
The next sections discuss each of these steps in detail.
Declaring The Cursor
The DECLARE CURSOR statement is used to associate a cursor name
with a query. The syntax of the DECLARE CURSOR command is as
follows:
DECLARE cursor-name CURSOR [WITH HOLD] FOR select-statementWhere cursor-name is a short identifier (8 or fewer characters), and select-statement is a valid DB2 select-statement (refer to the DB2 SQL Reference). The DECLARE CURSOR command causes the SQL host command environment to reserve an internal, statically declared cursor for use with the cursor-name. If you specify "WITH HOLD", the cursor will remain open across COMMITs. If you do not specify "WITH HOLD", the cursor will be closed automatically by a COMMIT statement. Both "hold" and "no hold" cursors are closed automatically by a ROLLBACK statement.
Note: Each task may have up to 10 "no hold" and 10 "hold" cursors in use at any one time.
The select-statement component, which is saved for use in processing the OPEN statement, may contain host variable expressions. The values of host variable expressions are resolved when the cursor is opened (not when it is declared). An INTO clause is not supported in this context. You may, however, use an INTO clause in a FETCH statement.
The data structures associated with a declared cursor are valid
until a FREE CURSOR statement is executed, or the task under
which the cursor was declared terminates.
Opening The Cursor
When an OPEN is executed, the interface PREPAREs the SELECT
statement associated with the cursor, and executes an internal
static OPEN statement. The OPEN causes DB2 to process the query,
thereby creating a result table (a temporary table used to hold
the retrieved columns and rows).
The OPEN statement has the following syntax:
OPEN cursor-nameWhere cursor-name is the name of a cursor that was previously DECLAREd.
The OPEN statement does not support a USING clause, because you
are permitted to code host variable references (see the topic
"Variables")
directly in the SELECT component of the DECLARE CURSOR command.
When an OPEN statement is processed, all host variable
expressions contained within the select-statement are resolved.
Fetching Rows
Rows are read from the result table using the FETCH statement.
The FETCH statement has the following syntax:
FETCH cursor-name [INTO host-var-expres[,host- var-expres...]]Where cursor-name is the name of a cursor that was previously DECLAREd and OPENed. The FETCH statement returns the next row in the result table (or a non- zero SQLCODE if no more rows are available). The column values of the fetched row are converted as required, and placed into REXX variables. The names of these variables can be specified in the optional INTO clause. If you do not specify an INTO clause, the names of the columns retrieved are used to create REXX variable names (see "Variables" for more on this subject).
CLOSE {cursor-name|*}Where cursor-name is the name of a cursor that was previously DECLAREd and OPENed. If you do not explicitly close a cursor, DB2 will close it when a COMMIT is issued ("no hold" cursors only), or when the task that executed the OPEN statement terminates. If you use the asterisk (*) format, all currently open cursors will be closed.
Note that closing a cursor does not free the data structures
associated with the cursor-name. To do that you must use the
FREE statement.
Freeing The Cursor
After you have closed a cursor, and if you don't plan on opening
it again, you should free the cursor so that the internal static
cursor can be reused. To free a cursor, use the FREE statement
(Refer to the topic
"FREE CURSOR").
Updating And Deleting Rows
The UPDATE and DELETE statements may be used to process the
current row of the result table. To update or delete the current
row of the result table, use the "WHERE CURRENT OF cursor-name"
clause with the appropriate statement. For example:
/* Declare the cursor */ "declare empcsr cursor for", "select lastname, salary", "from dsn8230.emp", "for update of salary" /* open the cursor */ "open empcsr" if rc<>0 then exit /* Loop through the rows of the result table updating rows where the salary is zero */ basesal = 10000 "fetch empcsr into :lname, :salary" do while rc=0 say lname salary if salary = 0 then "update dsn8230.emp", "set salary = :basesal", "where current of empcsr" "fetch empcsr into :lname, :salary" end /* close and free the cursor */ "close empcsr" "free empcsr cursor"
Notes:
basesal = 10000 "update dsn8410.emp", "set salary = :basesal", "where salary = 0"