Sie sind auf Seite 1von 41

Cursor in DB2

Row retrieval with a cursor


DB2 has a mechanism called a cursor. Using a cursor is like keeping your finger on a particular line
of text on a printed page.

In DB2, an application program uses a cursor to point to one or more rows in a set of rows that are
retrieved from a table. You can also use a cursor to retrieve rows from a result set that is returned by a
stored procedure. Your application program can use a cursor to retrieve rows from a table.

You can retrieve and process a set of rows that satisfy the search condition of an SQL statement.
When you use a program to select the rows, the program processes one or more rows at a time.

The SELECT statement must be within a DECLARE CURSOR statement and cannot include an INTO
clause. The DECLARE CURSOR statement defines and names the cursor, identifying the set of rows
to retrieve with the SELECT statement of the cursor. This set of rows is referred to as the result table.

After the DECLARE CURSOR statement executes, you process the result table of a cursor as follows:

1. Open the cursor before you retrieve any rows.

To tell DB2 that you are ready to process the first row of the result table, have your program
issue the OPEN statement. DB2 then uses the SELECT statement within the DECLARE
CURSOR statement to identify a set of rows. If you use host variables in that SELECT
statement, DB2 uses the current value of the variables to select the rows.

2. Use a FETCH statement to retrieve one or more rows.

The simplest form of the FETCH statement retrieves a single row of the result table by using a
row-positioned cursor. At any point in time, a row-positioned cursor retrieves at most a single
row from the result table into host variables. You can use a FETCH statement to retrieve more
than one row of the result table by using a cursor that is enabled to process rowsets. A rowset
is a set of rows that is retrieved through a multiple-row fetch.

When your program issues a row-positioned FETCH statement, DB2 uses the cursor to
point to a row in the result table, making it the current row. DB2 then moves the current row
contents into the program host variables that you specified in the INTO clause of the FETCH
statement. The FETCH statement moves the cursor. You can use host variable arrays and
return multiple rows of data with a single FETCH statement.

3. Close the cursor when the end-of-data condition occurs.

If you finish processing the rows of the result table and you want to use the cursor again,
issue a CLOSE statement to close the cursor.

Recommendation: Explicitly close the cursor when you finish using it.
Your program can have several cursors. Each cursor has the following requirements:

DECLARE CURSOR statement to define the cursor


OPEN and CLOSE statements to open and close the cursor
FETCH statement to retrieve rows from the result table of the cursor

You must declare host variables before you refer to them in a DECLARE CURSOR statement. To
define and identify a set of rows that are to be accessed with a cursor, issue a DECLARE CURSOR
statement. The DECLARE CURSOR statement names a cursor and specifies a SELECT statement.
The SELECT statement defines the criteria for the rows that belong in the result table.

You can use cursors to fetch, update, or delete one or more rows of a table, but you cannot use them
to insert a row into a table.

Suppose that your program examines data about people in department D11 and keeps the data in the
EMP table. The following examples show the SQL statements that you must include in a COBOL
program to define and use a cursor. In these examples, the program uses the cursor to process a set
of rows from the EMP table.

Example: Define the cursor: The following statement defines a cursor named THISEMP:
EXEC SQL
DECLARE THISEMP CURSOR FOR
SELECT EMPNO, LASTNAME,
DEPT, JOB
FROM EMP
WHERE DEPT = 'D11'
FOR UPDATE OF JOB
END-EXEC.
Example: Open the cursor: The following statement opens the cursor:
EXEC SQL
OPEN THISEMP
END-EXEC.
Example: Use the cursor to retrieve a row: The following statement uses the cursor, THISEMP, to
retrieve a row:
EXEC SQL
FETCH THISEMP
INTO :EMP-NUM, :NAME2,
:DEPT, :JOB-NAME
END-EXEC.
Example: Update the current row using the cursor: The following statement uses the cursor,
THISEMP, to update the JOB value for specific employees in department D11:
EXEC SQL
UPDATE EMP
SET JOB = :NEW-JOB
WHERE CURRENT OF THISEMP
END-EXEC.
Example: Close the cursor: The following statement closes the cursor:
EXEC SQL
CLOSE THISEMP
END-EXEC.

If the cursor is not scrollable, each fetch positions the cursor at the next sequential row, or set of
rows. A scrollable cursor can scroll forward and backward, and can be repositioned at the beginning, at
the end, or at a relative offset point. Applications can use a powerful set of SQL statements to fetch
data by using a cursor in random order. Scrollable cursors are especially useful for screen-based
applications. You can specify that the data in the result table is to remain static. For example, an
accounting application can require that data is to remain constant, whereas an airline reservation
system application must display the latest flight availability information.
You can also define options on the DECLARE CURSOR statement that specify how sensitive a
scrollable cursor is to changes in the underlying data when inserts, updates, or deletes occur.

A sensitive cursor is sensitive to changes that are made to the database after the result table
is generated. For example, when an application executes positioned UPDATE and DELETE
statements with the cursor, those changes are visible in the result table.
An insensitive cursor is not sensitive to inserts, updates, or deletes that are made to the
underlying rows of a result table after the result table is generated. For example, the order of
the rows and the values for each row of the result table do not change after the application
opens the cursor.

To indicate that a cursor is scrollable, you declare it with the SCROLL keyword.

Example: The following example shows a declaration for an insensitive scrollable cursor:
EXEC SQL DECLARE C1 INSENSITIVE SCROLL CURSOR FOR
SELECT DEPTNO, DEPTNAME, MGRNO
FROM DEPT
ORDER BY DEPTNO
END-EXEC.

To use this cursor to fetch the fifth row of the result table, you can use a FETCH statement like the
following example:

EXEC SQL FETCH ABSOLUTE +5 C1 INTO :HVDEPTNO, :DEPTNAME, :MGRNO;

Declare Cursor:

DECLARE CURSOR
The DECLARE CURSOR statement defines a cursor.

Invocation
This statement can only be embedded in an application program. It is not an executable statement. It
must not be specified in Java.

Authorization
For each table or view identified in the SELECT statement of the cursor, the privilege set must include
at least one of the following:

The SELECT privilege


Ownership of the object
DBADM authority for the corresponding database (tables only)
SYSADM authority
SYSCTRL authority (catalog tables only)

If the select-statement contains an SQL data change statement, the authorization requirements of
that statement also apply to the DECLARE CURSOR statement.

The SELECT statement of the cursor is one of the following:


The prepared select statement identified by statement-name
The specified select-statement

If statement-name is specified:

The privilege set is determined by the DYNAMICRULES behavior in effect (run, bind, define,
or invoke) and is summarized in Table 1. (For more information on these behaviors, including
a list of the DYNAMICRULES bind option values that determine them, see Authorization IDs
and dynamic SQL.)
The authorization check is performed when the SELECT statement is prepared.
The cursor cannot be opened unless the SELECT statement is successfully prepared.

If select-statement is specified:

The privilege set consists of the privileges that are held by the authorization ID of the owner of
the plan or package.
If the plan or package is bound with VALIDATE(BIND), the authorization check is performed at
bind time, and the bind is unsuccessful if any required privilege does not exist.
If the plan or package is bound with VALIDATE(RUN), an authorization check is performed at
bind time, but all required privileges need not exist at that time. If all privileges exist at bind
time, no authorization checking is performed when the cursor is opened. If any privilege does
not exist at bind time, an authorization check is performed the first time the cursor is opened
within a unit of work. The OPEN is unsuccessful if any required privilege does not exist.

Syntax

.-NO SCROLL------------------------.
>>-DECLARE--cursor-name--+----------------------------------+--->
| .-ASENSITIVE------------. |
'-+-----------------------+-SCROLL-'
+-INSENSITIVE-----------+
| .-DYNAMIC-. |
'-SENSITIVE-+---------+-'
'-STATIC--'

.-----------------------------.
V (1) |
>--CURSOR---------+--------------------+-+---------------------->
+-holdability--------+
+-returnability------+
'-rowset-positioning-'

>--FOR--+-select-statement-+-----------------------------------><
'-statement-name---'

Notes:
1. The same clause must not be specified more than once.

holdability:
.-WITHOUT HOLD-.
>>-+--------------+--------------------------------------------><
'-WITH HOLD----'

returnability:

.-WITHOUT RETURN-------------.
>>-+----------------------------+------------------------------><
| .-TO CALLER-. |
'-WITH RETURN--+-----------+-'

rowset-positioning:

.-WITHOUT ROWSET POSITIONING-.


>>-+----------------------------+------------------------------><
'-WITH ROWSET POSITIONING----'

Description
cursor-name
Names the cursor. The name must not identify a cursor that has already been declared in the
source program. The name is usually VARCHAR(128); however, if the cursor is defined WITH
RETURN, the name is limited to VARCHAR(30).
NO SCROLL or SCROLL
Specifies whether the cursor is scrollable or not scrollable.
NO SCROLL
Specifies that the cursor is not scrollable. This is the default.
SCROLL
Specifies that the cursor is scrollable. For a scrollable cursor, whether the cursor has
sensitivity to inserts, updates, or deletes depends on the cursor sensitivity option in effect for
the cursor. If a sensitivity option is not specified, ASENSITIVE is the default.
ASENSITIVE
Specifies that the cursor should be as sensitive as possible. This is the default.

A cursor that defined as ASENSITIVE will be either insensitive or sensitive dynamic; it will not
be sensitive static. For information about how the effective sensitivity of the cursor is returned
to the application with the GET DIAGNOSTICS statement or in the SQLCA, see OPEN.

INSENSITIVE
Specifies that the cursor does not have sensitivity to inserts, updates, or deletes that are
made to the rows underlying the result table. As a result, the size of the result table, the order
of the rows, and the values for each row do not change after the cursor is opened. In addition,
the cursor is read-only. The SELECT statement or attribute-string of the PREPARE statement
cannot contain a FOR UPDATE clause, and the cursor cannot be used for positioned updates
or deletes.
SENSITIVE
Specifies that the cursor has sensitivity to changes that are made to the database after the
result table is materialized. The cursor is always sensitive to updates and deletes that are
made using the cursor (that is, positioned updates and deletes using the same cursor). When
the current value of a row no longer satisfies the select-statement or statement-name, that
row is no longer visible through the cursor. When a row of the result table is deleted from the
underlying base table, the row is no longer visible through the cursor.

If DB2 cannot make changes visible to the cursor, then an error is issued at bind time for
OPEN CURSOR. DB2 cannot make changes visible to the cursor when the cursor implicitly
becomes read-only. For example, when the result table must be materialized, as when the
FROM clause of the SELECT statement contains more than one table or view. The current list
of conditions that result in an implicit read-only cursor can be found in Read-only cursors.

The default is DYNAMIC.

DYNAMIC
Specifies that the result table of the cursor is dynamic, meaning that the size of the result
table might change after the cursor is opened as rows are inserted into or deleted from the
underlying table, and the order of the rows might change. Rows that are inserted, deleted, or
updated by statements that are executed by the same application process as the cursor are
visible to the cursor immediately. Rows that are inserted, deleted, or updated by statements
that are executed by other application processes are visible only after the statements are
committed. If a column for an ORDER BY clause is updated via a cursor or any means
outside the process, the next FETCH statement behaves as if the updated row was deleted
and re-inserted into the result table at its correct location. At the time of a positioned update,
the cursor is positioned before the next row of the original location and there is no current row,
making the row appear to have moved.

If a SENSITIVE DYNAMIC cursor is not possible, an error is returned. For example, if a


temporary table is needed (such as for processing a FETCH FIRST n ROWS ONLY clause),
an error is returned. The SELECT statement of a cursor that is defined as SENSITIVE
DYNAMIC cannot contain an SQL data change statement.

STATIC
Specifies that the size of the result table and the order of the rows do not change after the
cursor is opened. Rows inserted into the underlying table are not added to the result table
regardless of how the rows are inserted. Rows in the result table do not move if columns in
the ORDER BY clause are updated in rows that have already been materialized. Positioned
updates and deletes are allowed if the result table is updatable. The SELECT statement of a
cursor that is defined as SENSITIVE STATIC cannot contain an SQL data change statement.

A STATIC cursor has visibility to changes made by this cursor using positioned updates or
deletes. Committed changes made outside this cursor are visible with the SENSITIVE option
of the FETCH statement. A FETCH SENSITIVE can result in a hole in the result table (that is,
a difference between the result table and its underlying base table). If an updated row in the
base table of a cursor no longer satisfies the predicate of its SELECT statement, an update
hole occurs in the result table. If a row of a cursor was deleted in the base table, a delete hole
occurs in the result table. When a FETCH SENSITIVE detects an update hole, no data is
returned (a warning is issued), and the cursor is left positioned on the update hole. When a
FETCH SENSITIVE detects a delete hole, no data is returned (a warning is issued), and the
cursor is left positioned on the delete hole.
Updates through a cursor result in an automatic re-fetch of the row. This re-fetch means that
updates can create a hole themselves. The re-fetched row also reflects changes as a result of
triggers updating the same row. It is important to reflect these changes to maintain the
consistency of data in the row.

Using a function that is not deterministic (built-in or user-defined) in the WHERE clause of the
select-statement or statement-name of a SENSITIVE STATIC cursor can cause misleading
results. This situation occurs because DB2 constructs a temporary result table and retrieves
rows from this table for FETCH INSENSITIVE statements. When DB2 processes a FETCH
SENSITIVE statement, rows are fetched from the underlying table and predicates are re-
evaluated. Using a function that is not deterministic can yield a different result on each FETCH
SENSITIVE of the same row, which could also result in the row no longer being considered a
match.

A FETCH INSENSITIVE on a SENSITIVE STATIC SCROLL cursor is not sensitive to changes


made outside the cursor, unless a previous FETCH SENSITIVE has already refreshed that
row; however, positioned updates and delete changes with the cursor are visible.

STATIC cursors are insensitive to insertions.

WITHOUT HOLD or WITH HOLD


Specifies whether the cursor should be prevented from being closed as a consequence of a
commit operation.
WITHOUT HOLD
Does not prevent the cursor from being closed as a consequence of a commit operation. This
is the default.
WITH HOLD
Prevents the cursor from being closed as a consequence of a commit operation. A cursor
declared with WITH HOLD is closed at commit time if one of the following is true:
The connection associated with the cursor is in the release pending status.
The bind option DISCONNECT(AUTOMATIC) is in effect.
The environment is one in which the option WITH HOLD is ignored.

When WITH HOLD is specified, a commit operation commits all of the changes in the current
unit of work. For example, with a non-scrollable cursor, an initial FETCH statement is needed
after a COMMIT statement to position the cursor on the row that follows the row that the
cursor was positioned on before the commit operation.

WITH HOLD has no effect on an SQL data change statement within a SELECT statement.
When a COMMIT is issued, the changes caused by the SQL data change statement are
committed, regardless of whether or not the cursor is declared WITH HOLD.

All cursors are implicitly closed by a connect (Type 1) or rollback operation. A cursor is also
implicitly closed by a commit operation if WITH HOLD is ignored or not specified.

Cursors that are declared with WITH HOLD in CICS or in IMS non-message-driven
programs will not be closed by a rollback operation if the cursor was opened in a previous unit
of work and no changes have been made to the database in the current unit of work. The
cursor cannot be closed because CICS and IMS do not broadcast the rollback request to DB2
for a null unit of work.

If a cursor is closed before the commit operation, the effect is the same as if the cursor was
declared without the option WITH HOLD.
WITH HOLD is ignored in IMS message driven programs (MPP, IFP, and message-driven
BMP). WITH HOLD maintains the cursor position in a CICS pseudo-conversational program
until the end-of-task (EOT).

For details on restrictions that apply to declaring cursors with WITH HOLD, see DB2
Application Programming and SQL Guide.

WITHOUT RETURN or WITH RETURN TO CALLER


Specifies the intended use of the result table of the cursor. The default is WITHOUT RETURN,
except in Java procedures, where the default is WITH RETURN TO CALLER.
WITHOUT RETURN
Specifies that the result table of the cursor is not intended to be used as a result set that will
be returned from the program or procedure.
WITH RETURN TO CALLER
Specifies that the result table of the cursor is intended to be used as a result set that will be
returned from the program or procedure to the caller. Specifying TO CALLER is optional.

WITH RETURN TO CALLER is relevant when the SQL CALL statement is used to invoke a
procedure that either contains the DECLARE CURSOR statement, or directly or indirectly
invokes a program or procedure that contains the DECLARE CURSOR statement. In other
cases, the precompiler might accept the clause, but the clause has no effect.

When a cursor that is declared using the WITH RETURN TO CALLER clause remains open at
the end of a program or procedure, that cursor defines a result set from the program or
procedure. Use the CLOSE statement to close cursors that are not intended to be a result set
from the program or procedure. Although DB2 will automatically close any cursors that are not
declared using WITH RETURN TO CALLER, the use of the CLOSE statement is
recommended to increase the portability of applications.

For non-scrollable cursors, the result set consists of all rows from the current cursor position
to the end of the result table. For scrollable cursors, the result set consists of all rows of the
result table.

The caller is the program or procedure that executed the SQL CALL statement that either
invokes the procedure that contains the DECLARE CURSOR statement, or directly or
indirectly invokes the program that contains the DECLARE CURSOR statement. For example,
if the caller is a procedure, the result set is returned to the procedure. If the caller is a client
application, the result set is returned to the client application.

rowset-positioning
Specifies whether multiple rows of data can be accessed as a rowset on a single FETCH
statement for the cursor. The default is WITHOUT ROWSET POSITIONING.
WITHOUT ROWSET POSITIONING
Specifies that the cursor can be used only with row-positioned FETCH statements. The cursor
is to return a single row for each FETCH statement and the FOR n ROWS clause cannot be
specified on a FETCH statement for this cursor. WITHOUT ROWSET POSITIONING or single
row access refers to how data is fetched from the database engine. For remote access, data
might be blocked and returned to the client in blocks.
WITH ROWSET POSITIONING
Specifies that the cursor can be used with either row-positioned or rowset-positioned FETCH
statements. This cursor can be used to return either a single row or multiple rows, as a
rowset, with a single FETCH statement. ROWSET POSITIONING refers to how data is
fetched from the database engine. For remote access, if any row qualifies, at least 1 row is
returned as a rowset. The size of the rowset depends on the number of rows specified on the
FETCH statement and on the number of rows that qualify. Data might be blocked and returned
to the client in blocks.
select-statement
Specifies the result table of the cursor. See select-statement for an explanation of select-
statement.

The select-statement must not include parameter markers (except for REXX), but can include
references to host variables. In host languages, other than REXX, the declarations of the host
variables must precede the DECLARE CURSOR statement in the source program. In REXX,
parameter markers must be used in place of host variables and the statement must be
prepared.

The USING clause of the OPEN statement can be used to specify host variables that will
override the values of the host variables or parameter markers that are specified as part of the
statement in the DECLARE CURSOR statement.

The select-statement of the cursor must not contain an SQL data change statement if the
cursor is defined as SENSITIVE DYNAMIC or SENSITIVE STATIC.

statement-name
Identifies the prepared select-statement that specifies the result table of the cursor whenever
the cursor is opened. The statement-name must not be identical to a statement name
specified in another DECLARE CURSOR statement of the source program. For an
explanation of prepared SELECT statements, see PREPARE.

The prepared select-statement of the cursor must not contain an SQL data change
statement if the cursor is defined as SENSITIVE DYNAMIC or SENSITIVE STATIC.

Notes
A cursor in the open state designates a result table and a position relative to the
rows of that table. The table is the result table specified by the SELECT statement
of the cursor.

Read-only cursors: If the result table is read-only, the cursor is read-only. The
cursor that references a view with instead of triggers are read-only since
positioned UPDATE and positioned DELETE statements are not allowed using
those cursors. The result table is read-only if one or more of the following
statements is true about the SELECT statement of the cursor:

The first FROM clause identifies or contains any of the following:


o More than one table or view
o A catalog table with no updatable columns
o A read-only view
o A nested table expression
o A table function
o A system-maintained materialized query table
The first SELECT clause specifies the keyword DISTINCT, contains an
aggregate function, or uses both
It contains an SQL data change statement
The outer subselect contains a GROUP BY clause, a HAVING clause, or
both clauses
It contains a subquery such that the base object of the outer subselect,
and of the subquery, is the same table
Any of the following operators or clauses are specified:
o A set operator
o An ORDER BY clause (except when the cursor is declared as
SENSITIVE STATIC scrollable)
o A FOR READ ONLY clause
It is executed with isolation level UR and a FOR UPDATE clause is not
specified.

If the result table is not read-only, the cursor can be used to update or delete the
underlying rows of the result table.

Work file database requirement for static scrollable cursors: To use a static
scrollable cursor, you must first create a work file database and at least one table
space with a 32KB page size in this database because a static scrollable cursor
requires a temporary table for its result table while the cursor is open. DB2
chooses a table space to use for the temporary result table. Dynamic scrollable
cursors do not require a declared temporary table.

Cursors in COBOL and Fortran programs: In COBOL and Fortran source


programs, the DECLARE CURSOR statement must precede all statements that
explicitly refer to the cursor by name. This rule does not necessarily apply to the
other host languages because the precompiler provides a two-pass option for
these languages. This rule applies to other host languages if the two-pass option is
not used.

Cursors in REXX: If host variables are used in a DECLARE CURSOR statement


within a REXX procedure, the DECLARE CURSOR statement must be the object
of a PREPARE and EXECUTE.

Scope of a cursor: The scope of cursor-name is the source program in which it is


defined; that is, the application program submitted to the precompiler. Thus, you
can only refer to a cursor by statements that are precompiled with the cursor
declaration. For example, a COBOL program called from another program cannot
use a cursor that was opened by the calling program. Furthermore, a cursor
defined in a Fortran subprogram can only be referred to in that subprogram.
Cursors that specify WITH RETURN in a procedure and are left open are returned
as result sets.

Although the scope of a cursor is the program in which it is declared, each


package (or DBRM of a plan) created from the program includes a separate
instance of the cursor, and more than one instance of the cursor can be used in
the same execution of the program. For example, assume a program is
precompiled with the CONNECT(2) option and its DBRM is used to create a
package at location X and a package at location Y. The program contains the
following SQL statements:
DECLARE C CURSOR FOR ...
CONNECT TO X
OPEN C
FETCH C INTO ...
CONNECT TO Y
OPEN C
FETCH C INTO ...
The second OPEN C statement does not cause an error because it refers to a
different instance of cursor C. The same notion applies to a single location if the
packages are in different collections.

A SELECT statement is evaluated at the time the cursor is opened. If the same
cursor is opened, closed, and then opened again, the results can be different. If
the SELECT statement of the cursor contains CURRENT DATE, CURRENT TIME
or CURRENT TIMESTAMP, all references to these special registers yields the
same respective datetime value on each FETCH operation. The value is
determined when the cursor is opened. Multiple cursors using the same SELECT
statement can be opened concurrently. They are each considered independent
activities.

Blocking of data: To process data more efficiently, DB2 might block data for read-
only cursors. If a cursor is not going to be used in a positioned UPDATE or
positioned DELETE statement, define the cursor as FOR READ ONLY.

Positioned deletes and isolation level UR: Specify FOR UPDATE if you want to
use the cursor for a positioned DELETE and the isolation level is UR because of a
BIND option. In this case, the isolation level is CS.

Returning a result set from a stored procedure: A cursor that is declared in a


stored procedure returns a result set when all of the following conditions are true:

The cursor is declared with the WITH RETURN option. In a distributed


environment, blocks of each result set of the cursor's data are returned
with the CALL statement reply.
The cursor is left open after exiting from the stored procedure. A cursor
declared with the SCROLL option must be left positioned before the first
row before exiting from the stored procedure.
The cursor is declared with the WITH HOLD option if the stored
procedure is defined to commit on return.

The result set is the set of all rows after the current position of the cursor after
exiting the stored procedure. The result set is assumed to be read-only. If that
same procedure is reinvoked, open result set cursors for a stored procedure at a
given site are automatically closed by the database management system.

Scrollable cursors specified with user-defined functions: A row can be fetched


more than once with a scrollable cursor. Therefore, if a scrollable cursor is defined
with a function that is not deterministic in the select list of the cursor, a row can be
fetched multiple times with different results for each fetch. (However, the value of a
funtion that is not deterministic in the WHERE clause of a scrollable cursor is
captured when the cursor is opened and remains unchanged until the cursor is
closed.) Similarly, if a scrollable cursor is defined with a user-defined function with
external action, the action is executed with every fetch.

Examples
The statements in the following examples are assumed to be in PL/I programs.

Example 1: Declare C1 as the cursor of a query to retrieve data from the table
DSN8910.DEPT. The query itself appears in the DECLARE CURSOR statement.

EXEC SQL DECLARE C1 CURSOR FOR


SELECT DEPTNO, DEPTNAME, MGRNO
FROM DSN8910.DEPT
WHERE ADMRDEPT = 'A00';
Example 2: Declare C1 as the cursor of a query to retrieve data from the table
DSN8810.DEPT. Assume that the data will be updated later with a searched
update and should be locked when the query executes. The query itself appears in
the DECLARE CURSOR statement.
EXEC SQL DECLARE C1 CURSOR FOR
SELECT DEPTNO, DEPTNAME, MGRNO
FROM DSN8910.DEPT
WHERE ADMRDEPT = 'A00'
FOR READ ONLY WITH RS USE AND KEEP EXCLUSIVE LOCKS;
Example 3: Declare C2 as the cursor for a statement named STMT2.

EXEC SQL DECLARE C2 CURSOR FOR STMT2;


Example 4: Declare C3 as the cursor for a query to be used in positioned updates
of the table DSN8910.EMP. Allow the completed updates to be committed from
time to time without closing the cursor.

EXEC SQL DECLARE C3 CURSOR WITH HOLD FOR


SELECT * FROM DSN8910.EMP
FOR UPDATE OF WORKDEPT, PHONENO, JOB, EDLEVEL, SALARY;
Instead of specifying which columns should be updated, you could use a FOR
UPDATE clause without the names of the columns to indicate that all updatable
columns are updated.
Example 5: In stored procedure SP1, declare C4 as the cursor for a query of the
table DSN8910.PROJ. Enable the cursor to return a result set to the caller of SP1,
which performs a commit on return.

EXEC SQL DECLARE C4 CURSOR WITH HOLD WITH RETURN FOR


SELECT PROJNO, PROJNAME
FROM DSN8910.PROJ
WHERE DEPTNO = 'A01';
Example 6: In the following example, the DECLARE CURSOR statement
associates the cursor name C5 with the results of the SELECT and specifies that
the cursor is scrollable. C5 allows positioned updates and deletes because the
result table can be updated.

EXEC SQL DECLARE C5 SENSITIVE STATIC SCROLL CURSOR FOR


SELECT DEPTNO, DEPTNAME, MGRNO
FROM DSN8910.DEPT
WHERE ADMRDEPT = 'A00';
Example 7: In the following example, the DECLARE CURSOR statement
associates the cursor name C6 with the results of the SELECT and specifies that
the cursor is scrollable.

EXEC SQL DECLARE C6 INSENSITIVE SCROLL CURSOR FOR


SELECT DEPTNO, DEPTNAME, MGRNO
FROM DSN8910.DEPT
WHERE DEPTNO;
Example 8: The following example illustrates how an application program might
use dynamic scrollable cursors. First create and populate a table.
CREATE TABLE ORDER
(ORDERNUM INTEGER,
CUSTNUM INTEGER,
CUSTNAME VARCHAR(20),
ORDERDATE CHAR(8),
ORDERAMT DECIMAL(8,3),
COMMENTS VARCHAR(20));
Populate the table by inserting or loading about 500 rows.
EXEC SQL DECLARE CURSOR ORDERSCROLL
SENSITIVE DYNAMIC SCROLL FOR
SELECT ORDERNUM, CUSTNAME, ORDERAMT, ORDERDATE FROM
ORDER
WHERE ORDERAMT > 1000
FOR UPDATE OF COMMENTS;
Open the scrollable cursor.
OPEN CURSOR ORDERSCROLL;
Fetch forward from the scrollable cursor.
-- Loop-to-fill-screen
-- do 10 times
FETCH FROM ORDERSCROLL INTO :HV1, :HV2, :HV3, :HV4;
-- end
Fetch RELATIVE from the scrollable cursor.
-- Skip-forward-100-rows
FETCH RELATIVE +100
FROM ORDERSCROLL INTO :HV1, :HV2, :HV3, :HV4;

-- Skip-backward-50-rows
FETCH RELATIVE -50
FROM ORDERSCROLL INTO :HV1, :HV2, :HV3, :HV4;

Fetch ABSOLUTE from the scrollable cursor.


-- Re-read-the-third-row
FETCH ABSOLUTE +3
FROM ORDERSCROLL INTO :HV1, :HV2, :HV3, :HV4;

Fetch RELATIVE from scrollable cursor.


-- Read-the-third-row-from current position
FETCH SENSITIVE RELATIVE +3
FROM ORDERSCROLL INTO :HV1, :HV2, :HV3, :HV4;

Do a positioned update through the scrollable cursor.


-- Update-the-current-row
UPDATE ORDER SET COMMENTS = "Expedite"
WHERE CURRENT OF ORDERSCROLL;

Close the scrollable cursor.


CLOSE CURSOR ORDERSCROLL;
Example 9: Declare C1 as the cursor of a query to retrieve a rowset from the table
DEPT. The prepared statement is MYCURSOR.
EXEC SQL DECLARE C1 CURSOR
WITH ROWSET POSITIONING FOR MYCURSOR;

FETCH
The FETCH statement positions a cursor on a row of its result table. It can return zero, one, or multiple
rows and assigns the values of the rows to host variables if there is a target specification.

There are two forms of this statement:

Single row fetch: positions the cursor and, optionally, retrieves data from a single row of the
result table.
Multiple row fetch: positions the cursor on zero or more rows of the result table and,
optionally, returns data if there is a target specification.

Invocation
This statement can only be embedded in an application program. It is an executable statement that
cannot be dynamically prepared. Multiple row fetch is not supported in REXX, Fortran 1, or SQL
Procedure applications.

Authorization
See DECLARE CURSOR for an explanation of the authorization required to use a cursor.

Syntax

>>-FETCH--+-----------------+--+-------------------+------------>
| (1) | | (3) |
+-INSENSITIVE-----+ '-WITH CONTINUE-----'
| (2) |
'-SENSITIVE-------'

.-FROM-.
>--| fetch-orientation |--+------+--cursor-name----------------->

>--+------------------------+----------------------------------><
+-| single-row-fetch |---+
'-| multiple-row-fetch |-'

Notes:
1. The default depends on the sensitivity of the cursor. If INSENSITIVE is specified on the
DECLARE CURSOR, then the default is INSENSITIVE and if SENSITIVE is specified on the
DECLARE CURSOR, then the default is SENSITIVE.
2. If INSENSITIVE or SENSITIVE is specified, single-row-fetch or multiple-row-fetch must be
specified.
3. If WITH CONTINUE is specified, single-row-fetch must be specified.

fetch-orientation

fetch-orientation

(1)
|--+-BEFORE----------------+------------------------------------|
| (1) |
+-AFTER-----------------+
+-| row-positioned |----+
'-| rowset-positioned |-'

row-positioned

.-NEXT--------------------------.
|--+-------------------------------+----------------------------|
+-PRIOR-------------------------+
+-FIRST-------------------------+
+-LAST--------------------------+
+-CURRENT--+----------+---------+
| '-CONTINUE-' |
+-ABSOLUTE-+-host-variable----+-+
| '-integer-constant-' |
'-RELATIVE-+-host-variable----+-'
'-integer-constant-'

rowset-positioned

|--+-NEXT ROWSET------------------------------------------+-----|
+-PRIOR ROWSET-----------------------------------------+
+-FIRST ROWSET-----------------------------------------+
+-LAST ROWSET------------------------------------------+
+-CURRENT ROWSET---------------------------------------+
'-ROWSET STARTING AT-+-ABSOLUTE-+-+-host-variable----+-'
'-RELATIVE-' '-integer-constant-'

Notes:
1. If BEFORE or AFTER is specified, SENSITIVE, INSENSITIVE, single-row-fetch, or multiple-
row-fetch must not be specified.

fetch-type

single-row-fetch

(1)
|--+---------------------------------+--------------------------|
| .-,-------------. |
| V | |
+-INTO---host-variable-+----------+
'-INTO DESCRIPTOR descriptor-name-'

multiple-row-fetch

(2)
|--+---------------------------------+-------------------------->
'-FOR--+-host-variable----+--ROWS-'
'-integer-constant-'

>--+---------------------------------+--------------------------|
| .-,-------------------. |
| V | |
+-INTO----host-variable-array-+---+
'-INTO DESCRIPTOR descriptor-name-'

Notes:
1. For single-row-fetch, a host-variable-array can be specified instead of a host variable and the
descriptor can describe host-variable-arrays. In either case, data is returned only for the first
entry of the host-variable-array.
2. This clause is optional. If this clause is not specified and either a rowset size has not been
established yet or a row positioned FETCH statement was the last type of FETCH statement
issued for this cursor, the rowset size is implicitly one. If the last FETCH statement issued for
this cursor was a rowset positioned FETCH statement and this clause is not specified, the
rowset size is the same size as the previous rowset positioned FETCH.

Description
INSENSITIVE
Returns the row from the result table as it is. If the row has been previously fetched with a
FETCH SENSITIVE, it reflects changes made outside this cursor before the FETCH
SENSITIVE statement was issued. Positioned updates and deletes are reflected with FETCH
INSENSITIVE if the same cursor was used for the positioned update or delete.

INSENSITIVE can only be specified for cursors declared as INSENSITIVE or SENSITIVE


STATIC (or if the cursor is declared as ASENSITIVE and DB2 defaults to INSENSITIVE).
Otherwise, if the cursor is declared as SENSITIVE DYNAMIC (or if the cursor is declared as
ASENSITIVE and DB2 defaults to SENSITIVE DYNAMIC), an error occurs and the FETCH
statement has no effect. For an INSENSITIVE cursor, specifying INSENSITIVE is optional
because it is the default.

SENSITIVE
Updates the fetched row in the result table from the corresponding row in the base table of the
cursor's SELECT statement and returns the current values. Thus, it reflects changes made
outside this cursor. SENSITIVE can only be specified for a sensitive cursor. Otherwise, if the
cursor is insensitive, an error occurs and the FETCH statement has no effect. For a
SENSITIVE cursor, specifying SENSITIVE is optional because it is the default.

When the cursor is declared as SENSITIVE STATIC and a FETCH SENSITIVE is requested,
the following steps are taken:

1. DB2 retrieves the row of the database that corresponds to the row of the result table
that is about to be fetched.
2. If the corresponding row has been deleted, a "delete hole" occurs in the result table,
a warning is issued, the cursor is repositioned on the "hole", and no data is fetched.
(DB2 marks a row in the result table as a "delete hole" when the corresponding row in
the database is deleted.)
3. If the corresponding row has not been deleted, the predicate of the underlying
SELECT statement is re-evaluated. If the row no longer satisfies the predicate, an
"update hole" occurs in the result table, a warning is issued, the cursor is repositioned
on the "hole," and no data is fetched. (DB2 marks a row in the result table as an
"update hole" when an update to the corresponding row in the database causes the
row to no longer qualify for the result table.)
4. If the corresponding row does not result in a delete or an update hole in the result
table, the cursor is repositioned on the row of the result table and the data is fetched.
WITH CONTINUE
Specifies that the DB2 subsystem should prepare to allow subsequent FETCH CURRENT
CONTINUE operations to access any truncated LOB or XML result column following an initial
FETCH operation that provides output variables that are not large enough to hold the entire
LOB or XML columns. When the WITH CONTINUE clause is specified, the DB2 subsystem
takes the following actions that can differ from the case where the FETCH statement does not
include the WITH CONTINUE clause:
If truncation occurs when returning an XML or LOB column, the DB2 subsystem will
remember the truncation position and will not discard the remaining data.
If truncation occurs when returning an XML or LOB column, the DB2 subsystem
returns the total length that would have been required to hold all of the data of the
LOB or XML column. This will either be in the first four bytes of the LOB host variable
structure or in the 4 byte area that is pointed to by the SQLDATALEN pointer in the
SQLVAR entry of the SQLDA for that host variable. What is returned depends on the
programming method that is used. See SQL descriptor area (SQLDA) for details
about the SQLDA contents.
If returning XML data, the result column will be fully materialized in the database
before the data is returned.

If the CURRENT CONTINUE clause is specified, the WITH CONTINUE behavior is


assumed.

AFTER
Positions the cursor after the last row of the result table. Values are not assigned to host
variables. The number of rows of the result table are returned in the SQLERRD1 and
SQLERRD2 fields of the SQLCA for cursors with an effective sensitivity of INSENSITIVE or
SENSITIVE STATIC.
BEFORE
Positions the cursor before the first row of the result table. Values are not assigned to host
variables.
row-positioned
Positioning of the cursor with row-positioned fetch orientations NEXT, PRIOR, CURRENT and
RELATIVE is done in relation to the current cursor position. Following a successful row-
positioned FETCH statement, the cursor is positioned on a single row of data. If the cursor is
enabled for rowsets, positioning is performed relative to the current row or the first row of the
current rowset, and the cursor is positioned on a rowset consisting of a single row.
NEXT
Positions the cursor on the next row or rows of the result table relative to the current cursor
position, and returns data if a target is specified. NEXT is the only row-positioned fetch
operation that can be explicitly specified for cursors that are defined as NO SCROLL. NEXT is
the default if no other cursor positioning is specified. If a specified row reflects a hole, a
warning is issued and data values are not assigned to host variables for that row.

Table 1 lists situations for different cursor positions and the results when NEXT is
used.

Table 1. Results when NEXT is used with different cursor positions

Current state of the cursor Result of FETCH NEXT

Before the first row Cursor is positioned on the first row (1) and
data is returned if requested.

On the last row or after the last row A warning occurs, values are not assigned to
host variables, and the cursor position is
unchanged.

Before a hole For a SENSITIVE STATIC cursor, a warning


occurs for a delete hole or an update hole,
values are not assigned to host variables, and
Table 1. Results when NEXT is used with different cursor positions

Current state of the cursor Result of FETCH NEXT

the cursor is positioned on the hole.

Unknown An error occurs, values are not assigned to


host variables, and the cursor position remains
unknown.

Note:

(1)This row is not applicable in the case of a forward-only cursor (that is when NO SCROLL
was specified implicitly or explicitly).

PRIOR
Positions the cursor on the previous row or rows of the result table relative to the current
cursor position, and returns data if a target is specified. If a specified row reflects a hole, a
warning is issued, and data values are not assigned to host variables for that row.

Table 2 lists situations for different cursor positions and the results when PRIOR is
used.

Table 2. Results when PRIOR is used with different cursor positions

Current state of the cursor Result of FETCH PRIOR

Before the first row or on the first row A warning occurs, values are not assigned to
host variables, and the cursor position is
unchanged.

After a hole For a SENSITIVE STATIC cursor, a warning


occurs for a delete hole or an update hole,
values are not assigned to host variables, and
the cursor is positioned on the hole.

After the last row Cursor is positioned on the last row.

Unknown An error occurs, values are not assigned to


host variables, and the cursor position remains
unknown.

FIRST
Positions the cursor on the first row of the result table, and returns data if a target is specified.
For a SENSITIVE STATIC cursor, if the first row of the result table is a hole, a warning occurs
for a delete hole or an update hole and values are not assigned to host variables.
LAST
Positions the cursor on the last row of the result table, and returns data if a target is specified.
The number of rows of the result table is returned in the SQLERRD1 and SQLERRD2 fields of
the SQLCA for an insensitive or sensitive static cursor. For a SENSITIVE STATIC cursor, if the
last row of the result table is a hole, a warning occurs for a delete hole or an update hole and
values are not assigned to host variables.
CURRENT
The cursor position is not changed, data is returned if a target is specified. If the cursor was
positioned on a rowset of more than one row, the cursor position is on the first row of the
rowset.

Table 3 lists situations in which errors occur with the CURRENT clause.

Table 3. Situations in which errors occur with CURRENT

Current state of the cursor Result of FETCH CURRENT

Before the first row or after the last row A warning occurs, values are not assigned to
host variables, and the cursor position is
unchanged.

On a hole For a SENSITIVE STATIC, a warning occurs for


a delete hole or an update hole, values are not
assigned to host variables, and the cursor is
positioned on the hole.

If the cursor is defined as a rowset cursor, with


isolation level UR or a sensitive dynamic
scrollable cursor, it is possible that a different
row will be returned than the FETCH that
established the most recent cursor position.
This can occur while fetching a row again when
it is determined to not be there anymore. In this
case, fetching continues moving forward to get
the row of data.

Unknown An error occurs, values are not assigned to


host variables, and the cursor position remains
unknown.

CONTINUE
The cursor positioning is not changed, and data is returned if a target is specified. The
FETCH CURRENT CONTINUE statement retrieves remaining data for any LOB or XML
column result values that were truncated on a previous FETCH or FETCH CURRENT
CONTINUE statement. It assigns the remaining data for those truncated columns to the host
variables that are referenced in the statement or pointed to by the descriptor. The data that is
returned for previously-truncated result values begins at the point of truncation. This form of
the CURRENT clause must only be used after a single-row FETCH WITH CONTINUE or
FETCH CURRENT CONTINUE statement that has returned partial data for one or more LOB
or XML columns. The cursor must be open and positioned on a row.
FETCH CURRENT CONTINUE must pass host variables entries for all columns in the
SELECT list, even though the non-LOB columns or non-XML columns will not return any data.

ABSOLUTE
host-variable or integer-constant is assigned to an integral value k. If a host-variable is
specified, it must be an exact numeric type with zero scale and must not include an indicator
variable. The possible data types for the host variable are DECIMAL( n,0) or integer. The
DECIMAL data type is limited to DECIMAL(18,0). An integer-constant can be up to 31 digits,
depending on the application language.

If k=0, the cursor is positioned before the first row of the result table. Otherwise, ABSOLUTE
positions the cursor to row k of the result table if k>0, or to k rows from the bottom of the table
if k<0. For example, "ABSOLUTE -1" is the same as "LAST".

Data is returned if the specified position is within the rows of the result table, and a target is
specified.

If an absolute position is specified that is before the first row or after the last row of the result
table, a warning occurs, values are not assigned to host variables, and the cursor is
positioned either before the first row or after the last row. If the resulting cursor position is after
the last row for INSENSITIVE and SENSITIVE STATIC scrollable cursors, the number of rows
of the result table are returned in the SQLERRD1 and SQLERRD2 fields of the SQLCA. If row
k of the result table is a hole, a warning occurs and values are not assigned to host variables.

FETCH ABSOLUTE 0 results in positioning before the first row and a warning is issued.
FETCH BEFORE results in positioning before the first row and no warning is issued.

Table 4 lists some synonymous specifications.

Table 4. Synonymous scroll specifications for ABSOLUTE

Specification Alternative

ABSOLUTE 0 (but with a warning) BEFORE (without a warning)

ABSOLUTE +1 FIRST

ABSOLUTE -1 LAST

ABSOLUTE -m, 0<mn ABSOLUTE n+1-m

ABSOLUTE n LAST

ABSOLUTE -n FIRST

ABSOLUTE x (with a warning) AFTER (without a warning)

ABSOLUTE -x (with a warning) BEFORE (without a warning)


Table 4. Synonymous scroll specifications for ABSOLUTE

Specification Alternative

Note: Assume: 0<=m<=n<x Where, n is the number of rows in the result table.

RELATIVE
host-variable or integer-constant is assigned to an integral value k. If a host-variable is
specified, it must be an exact numeric type with zero scale and must not include an indicator
variable. The possible data types for the host variable are DECIMAL( n,0) or integer. The
DECIMAL data type is limited to DECIMAL(18,0).

If the cursor is positioned before the first row, or after the last row of the result table, the
cursor position is determined as follows:

If n is 0, the cursor position is unchanged, values are not assigned to host variables,
and a warning occurs
If n is positive, and the cursor is positioned before the first row, the cursor is
positioned on a rowset starting at row n
If n is positive, and the cursor is positioned after the last row, a warning occurs
If n is negative, and the cursor is positioned before the first row, a warning occurs
If n is negative, and the cursor is positioned after the last row, the cursor is positioned
on a rowset starting as row n from the end of the result table

An integer-constant can be up to 31 digits, depending on the application language.

Data is returned if the specified position is within the rows of the result table, and a target is
specified.

RELATIVE positions the cursor to the row in the result table that is either k rows after the
current row if k>0, or ABS(k) rows before the current row if k<0. For example, "RELATIVE -1"
is the same as "PRIOR". If k=0, the position of the cursor does not change (that is,
"RELATIVE 0" is the same as "CURRENT").

If a relative position is specified that results in positioning before the first row or after the last
row, a warning is issued, values are not assigned to host variables, and the cursor is
positioned either before the first row or after the last row. If the resulting cursor position is after
the last row for INSENSITIVE and SENSITIVE STATIC scrollable cursors, the number of rows
of the result table is returned in the SQLERRD1 and SQLERRD2 fields of the SQLCA. If the
cursor is positioned on a hole and RELATIVE 0 is specified or if the target row is a hole, a
warning occurs and values are not assigned to host variables.

If the cursor is defined as a rowset cursor, with isolation level UR or a sensitive dynamic
scrollable cursor, it is possible that a different row will be returned than the FETCH that
established the most recent cursor position. This can occur while fetching a row again when it
is determined to not be there anymore. In this case, fetching continues moving forward to get
the row data.

If the cursor position is unknown and RELATIVE 0 is specified, an error occurs.


Table 5 lists some synonymous specifications.

Table 5. Synonymous Scroll Specifications for RELATIVE

Specification Alternative

RELATIVE +1 NEXT

RELATIVE -1 PRIOR

RELATIVE 0 CURRENT

RELATIVE +r (with a warning) AFTER (without a warning)

RELATIVE -r (with a warning) BEFORE (without a warning)

Note:

r has to be large enough to position the cursor beyond either end of the result table.

rowset-positioned

Positioning of the cursor with rowset-positioned fetch orientations NEXT ROWSET, PRIOR
ROWSET, CURRENT ROWSET, and ROWSET STARTING AT RELATIVE is done in relation
to the current cursor position. Following a successful row-positioned FETCH statement, the
cursor is positioned on a rowset of data. The number of rows in the rowset is determined
either explicitly or implicitly. The FOR n ROWS clause in the multiple-row-fetch clause is used
to explicitly specify the size of the rowset. Positioning is performed relative to the current row
or first row of the current rowset, and the cursor is positioned on all rows of the rowset.

A rowset-positioned fetch orientation must not be specified if the current cursor position is not
defined to access rowsets. NEXT ROWSET is the only rowset-positioned fetch orientation that
can be specified for cursors that are defined as NO SCROLL.

If a row of the rowset reflects a hole, a warning is returned, data values are not assigned to
host variable arrays for that row (that is, the corresponding positions in the target host variable
arrays are untouched), and -3 is returned in all provided indicator variables for that row. If a
hole is detected, and at least one indicator variable is not provided, an error occurs.

NEXT ROWSET
Positions the cursor on the next rowset of the result table relative to the current cursor
position, and returns data if a target is specified. The next rowset is logically obtained by
fetching the row that follows the current rowset and fetching additional rows until the number
of rows that is specified implicitly or explicitly in the FOR n ROWS clause is obtained or the
last row of the result table is reached.

If the cursor is positioned before the first row of the result table, the cursor is positioned on the
first rowset.
If the cursor is positioned on the last row or after the last row of the result table, the cursor
position is unchanged, values are not assigned to host variable arrays, and a warning occurs.

If a row of the rowset reflects a hole, the following actions occur:

A warning is returned.
Data values are not assigned to the host-variable-arrays for that row (that is, the
corresponding positions in the target host-variable-arrays are untouched).
A value of -3 is returned in all of the indicator variables that are provided for the row.

If a hole is detected and at least one indicator variable is not provided, an error is returned.

If the cursor is not positioned because of a prior error, values are not assigned to the host-
variable-array, and an error is returned. If a row of the rowset would be after the last row of the
result table, values are not assigned to host-variable-arrays for that row and any subsequent
requested rows of the rowset, and a warning is returned.

NEXT ROWSET is the only rowset positioned fetch orientation that can be explicitly be
specified for cursors that are defined as NO SCROLL.

PRIOR ROWSET
Positions the cursor on the previous rowset of the result table relative to the current position,
and returns data if a target is specified.

The prior rowset is logically obtained by fetching the row that precedes the current rowset and
fetching additional rows until the number of rows that is specified implicitly or explicitly in the
FOR n ROWS clause is obtained or the last row of the result table is reached.

If the cursor is positioned after the last row of the result table, the cursor is positioned on the
last rowset.

If the cursor is positioned before the first row or on the first row of the result table, the cursor
position is unchanged, values are not assigned to host variable arrays, and a warning occurs.

If a row would be before the first row of the result table, the cursor is positioned on a partial
rowset that consists of only those rows that are prior to the current position of the cursor
starting with the first row of the result table, and a warning is returned. Values are not
assigned to the host-variable-arrays for the rows in the rowset for which the warning is
returned.

Although the rowset is logically obtained by fetching backwards from before the current
rowset, the data is returned to the application starting with the first row of the rowset, to the
end of the rowset.

If a row of the rowset reflects a hole, the following actions occur:

A warning is returned.
Data values are not assigned to the host-variable-arrays for that row (that is, the
corresponding positions in the target host-variable-arrays are untouched).
A value of -3 is returned in all of the indicator variables that are provided for the row.

If a hole is detected and at least one indicator variable is not provided, an error is returned.
If the cursor is not positioned because of a prior error, values are not assigned to the host-
variable-array, and an error is returned.

FIRST ROWSET
Positions the cursor on the first rowset of the result table, and returns data if a target is
specified.

If a row of the rowset reflects a hole, the following actions occur:

A warning is returned.
Data values are not assigned to the host-variable-arrays for that row (that is, the
corresponding positions in the target host-variable-arrays are untouched).
A value of -3 is returned in all of the indicator variables that are provided for the row.

If a hole is detected and at least one indicator variable is not provided, an error is returned.

If the result table contains fewer rows than specified implicitly or explicitly in the FOR n ROWS
clause, values are not assigned to host-variable-arrays after the last row of the result table,
and a warning is returned.

LAST ROWSET
Positions the cursor on the last rowset of the result table and returns data if a target is
specified. The last rowset is logically obtained by fetching the last row of the result table and
fetching prior rows until the number of rows in the rowset is obtained or the first row of the
result table is reached. Although the rowset is logically obtained by fetching backwards from
the bottom of the result table, the data is returned to the application starting with the first row
of the rowset, to the end of the rowset, which is also the end of the result table.

If a row of the rowset reflects a hole, the following actions occur:

A warning is returned.
Data values are not assigned to the host-variable-arrays for that row (that is, the
corresponding positions in the target host-variable-arrays are untouched).
A value of -3 is returned in all of the indicator variables that are provided for the row.

If a hole is detected and at least one indicator variable is not provided, an error is returned.

If the result table contains fewer rows than specified implicitly or explicitly in the FOR n ROWS
clause, the last rowset is the same as the first rowset, values are not assigned to host-
variable-arrays after the last row of the result table, and a warning is returned.

CURRENT ROWSET
If the FOR n ROWS clause specifies a number different from the number of rows specified
implicitly or explicitly in the FOR n ROWS clause on the most recent FETCH statement for this
cursor, the cursor is repositioned on the specified number of rows, starting with the first row of
the current rowset. If the cursor is positioned before the first row, or after the last row of the
result table, the cursor position is unchanged, values are not assigned to host variable arrays,
and a warning occurs. If the FOR n ROWS clause is not specified, it is possible that the
FETCH statement will position the cursor on a partial rowset when the FETCH CURRENT
ROWSET statement is processed. In this case, DB2 attempts to position the cursor on a full
rowset starting with the first row of the current rowset. Otherwise, the position of the cursor on
the current rowset is unchanged. Data is returned if a target is specified.
With isolation level UR or a sensitive dynamic scrollable cursor, it is possible that different
rows will be returned than the FETCH that established the most recent rowset cursor position.
This can occur while refetching the first row of the rowset when it is determined to not be there
anymore. In this case, fetching continues moving forward to get the first row of data for the
rowset. This can also occur when changes have been made to other rows in the current
rowset such that they no longer exist or have been logically moved within (or out of) the result
table of the cursor.

If the cursor is not positioned because of a prior error, values are not assigned to the host-
variable-array, and an error occurs.

If the current rowset contains fewer rows than specified implicitly or explicitly in the FOR n
ROWS clause, values are not assigned to host-variable-arrays after the last row, and a
warning is returned.

ROWSET STARTING AT ABSOLUTE or RELATIVE host-variable or integer-


constant
Positions the cursor on the rowset beginning at the row of the result table that is indicated by
the ABSOLUTE or RELATIVE specification, and returns data if a target is specified.

host-variable or integer-constant is assigned to an integral value k. If host-variable is


specified, it must be an exact numeric type with scale zero, and must not include an indicator
variable. The possible data types for the host variable are DECIMAL(n,0) or integer, where the
DECIMAL data type is limited to DECIMAL(18,0). If a constant is specified, the value must be
an integer.

If a row of the result table would be after the last row or before the first row of the result table,
values are not assigned to host-variable-arrays for that row and a warning is returned.

ABSOLUTE
If k=0, an error occurs. If k>0, the first row of the rowset is row k. If k<0, the rowset is
positioned on the ABS(k) rows from the bottom of the result table. Assume that ABS(k) is
equal to the number of rows for the rowset and that there are enough row to return a complete
rowset:
FETCH ROWSET STARTING AT ABSOLUTE -k is the same as FETCH LAST
ROWSET.
FETCH ROWSET STARTING AT ABSOLUTE 1 is the same as FETCH FIRST
ROWSET.
RELATIVE
If k=0 and the FOR n ROWS clause does not specify a number different from the number
most recently specified implicitly or explicitly for this cursor, then the position of the cursor
does not change (that is, "RELATIVE ROWSET 0" is the same as "CURRENT ROWSET"). If
k=0 and the FOR n ROWS clause specifies a number different from the number most recently
specified implicitly or explicitly for this cursor, then the cursor is repositioned on the specified
number of rows, starting with the first row of the current rowset.

If the cursor is positioned before the first row, or after the last row of the result table, the
cursor position is determined as follows:

If n is 0, the cursor position is unchanged, values are not assigned to host variables,
and a warning occurs. This is the same as FETCH CURRENT ROWSET.
If n is positive, and the cursor is positioned before the first row, the cursor is
positioned on a rowset starting a row n.
If n is positive, and the cursor is positioned after the last row, a warning occurs.
If n is negative, and the cursor is positioned before the first row, a warning occurs.
If n is negative, and the cursor is positioned after the last row, the cursor is positioned
on a rowset starting at row n from the bottom of the result table.
Otherwise, RELATIVE repositions the cursor so that the first row of the new rowset cursor
position is on the row in the result table that is either k rows after the first row of the current
rowset cursor position if k>0, or ABS(k) rows before the first row of the current rowset cursor
position if k<0. Assume that ABS(k) is equal to the number of rows for the resulting rowset
FETCH ROWSET STARTING AT RELATIVE -k is the same as FETCH PRIOR
ROWSET.
FETCH ROWSET STARTING AT RELATIVE k is the same as FETCH NEXT
ROWSET.
FETCH ROWSET STARTING AT RELATIVE 0 is the same as FETCH CURRENT
ROWSET.

When ROWSET STARTING AT RELATIVE -n is specified and there are not enough rows
between the current position of the cursor and the beginning of the result table to return a
complete rowset:

A warning is returned.
Values are not assigned to the host-variable-arrays.
The cursor is positioned before the first row.

If a row of the rowset reflects a hole, If a row of the rowset reflects a hole, the following
actions occur:

A warning is returned.
Data values are not assigned to the host-variable-arrays for that row (that is, the
corresponding positions in the target host-variable-arrays are untouched).
A value of -3 is returned in all of the indicator variables that are provided for the
row.

If a hole is detected and at least one indicator variable is not provided, an error is
returned. If a row of the rowset is unknown, values are not assigned to host variable
arrays for that row, and an error is returned. If a row of the rowset would be after the last
row or before the first row of the result table, values are not assigned to host-variable-
arrays for that row, and a warning is returned.

cursor-name
Identifies the cursor to be used in the fetch operation. The cursor name must identify a
declared cursor, as explained in the description of the DECLARE CURSOR statement in
DECLARE CURSOR, or an allocated cursor, as explained in ALLOCATE CURSOR. When the
FETCH statement is executed, the cursor must be in the open state.

If a single-row-fetch or multiple-row-fetch clause is not specified, the cursor position is


adjusted as specified, but no data is returned to the user.

single-row-fetch
When single-row-fetch is specified, SENSITIVE or INSENSITIVE can be specified though
there is a default. The default depends on the sensitivity of the cursor. If the sensitivity of the
cursor is INSENSITIVE, then the default is INSENSITIVE. If the effective sensitivity of the
cursor is SENSITIVE DYNAMIC or SENSITIVE STATIC, then the default is SENSITIVE. The
single-row-fetch or multiple-row-fetch clause must not be specified when the FETCH BEFORE
or FETCH AFTER option is specified. They are required when FETCH BEFORE or FETCH
AFTER is not specified. If an individual fetch operation causes the cursor to be positioned or
to remain positioned on a row if there is a target specification, the values of the result table
are assigned to host variables as specified by the single-fetch-clause.
INTO host-variable,...
Specifies a list of host variables. Each host-variable must identify a structure or variable that is
described in the application program in accordance with the rules for declaring host structures
and variables. A reference to a structure is replaced by a reference to each of its variables.
The first value in the result row is assigned to the first host variable, the second value to the
second host variable, and so on.
INTO DESCRIPTOR descriptor-name
Identifies an SQLDA that contains a valid description of the host output variables. Result
values from the associated SELECT statement are returned to the application program in the
output host variables.

Before the FETCH statement is processed, you must set the following fields in the SQLDA:

SQLN to indicate the number of SQLVAR occurrences provided in the SQLDA

A REXX SQLDA does not contain this field.

SQLABC to indicate the number of bytes of storage allocated in the SQLDA


SQLD to indicate the number of variables used in the SQLDA when processing the
statement
SQLVAR occurrences to indicate the attributes of the variables

The SQLDA must have enough storage to contain all SQLVAR occurrences. Each SQLVAR
occurrence describes a host variable or buffer into which a value in the result table is to be
assigned. If LOBs are present in the results, there must be additional SQLVAR entries for
each column of the result table. If the result table contains only base types and distinct types,
multiple SQLVAR entries are not needed for each column. However, extra SQLVAR entries
are needed for distinct types as well as for LOBs in DESCRIBE and PREPARE INTO
statements. For more information on the SQLDA, which includes a description of the SQLVAR
and an explanation on how to determine the number of SQLVAR occurrences, see SQL
descriptor area (SQLDA).

SQLD must be set to a value greater than or equal to zero and less than or equal to SQLN.

See Identifying an SQLDA in C or C++ for how to represent descriptor-name in C.

multiple-row-fetch
Retrieves multiple rows of data from the result table of a query. The FOR n ROWS clause of
the FETCH statement controls how many rows are returned on a single FETCH statement.
The fetch orientation determines whether the resulting cursor position (for example, on a
single row, rowset, before, or after the result table). Fetching stops when an error is returned,
all requested rows are fetched, or the end of data condition is reached.

Fetching multiple rows of data can be done with scrollable or non-scrollable cursors. The
operations used to define, open, and close a cursor used for fetching multiple rows of data are
the same as for those used for single row FETCH statements.

If the BEFORE or AFTER option is specified, neither single-row-fetch or multiple-row-fetch


can be specified.

FOR host-variable or integer-constant ROWS


host-variable or integer-constant is assigned to an integral value k. If a host variable is
specified, it must be an exact numeric type with a scale of zero and must not include an
indicator variable. Furthermore, k must be in the range, 0<k<=32767.

This clause must not be specified if a row-positioned fetch-orientation clause was specified.
This clause must also not be specified for a cursor that is defined without rowset access.

If a rowset fetch orientation is specified and this clause is not specified, the number of rows in
the resulting rowset is determined as follows:

If the most recent FETCH statement for this cursor was a rowset-positioned FETCH,
the number of rows of the rowset is implicitly determined by the number of rows that
was most recently specified (implicitly or explicitly) for this cursor.
When the most recent FETCH statement for this cursor was either FETCH BEFORE
or FETCH AFTER and the most recent FETCH statement for this cursor prior to that
was a rowset-positioned FETCH, the number of rows of the rowset is implicitly
determined by the number of rows that were most recently specified (implicitly or
explicitly) for this cursor.
Otherwise, the rowset consists of a single row.

For result set cursors, the number of rows for a rowset cursor position, established in the
procedure that defined the rowset, is not inherited by the caller when the rowset is returned.
Use the FOR n ROWS clause on the first rowset FETCH statement for the result set in the
calling program to establish the number of rows for the cursor. Otherwise, the rowset consists
of a single row.

The cursor is positioned on the row or rowset that is specified by the orientation clause (for
example, NEXT ROWSET), and those rows are fetched if a target is specified. After the cursor
is positioned on the first row being fetched, the next k-1 rows are fetched. Fetching moves
forward from the cursor position in the result table and continues until the end of data
condition is returned, k-1 rows have been fetched, or an assignment error is returned.

The resulting cursor position depends on the fetch orientation that is specified:

For a row-positioned fetch orientation, the cursor is positioned at the last row
successfully retrieved.
For a rowset-positioned fetch orientation, the cursor is positioned on all the rows
retrieved.

The values from each individual fetch are placed in data areas that are described in the INTO
or USING clause. If a target specification is provided for a rowset-positioned FETCH, the host
variable arrays must be specified as the target specification, and the arrays must be defined
with a dimension of 1 or greater. The target specification must be defined as an array for a
rowset-positioned FETCH even if the number of rows that is specified implicitly or explicitly is
one. See Diagnostics information for rowset positioned FETCH statements.

INTO host-variable-array
Identifies for each column of the result table a host-variable-array to receive the data that is
retrieved with this FETCH statement. If the number of host-variable-arrays is less than the
number of columns of the result table, the SQLWARN3 field of the SQLCA is set to 'W'. No
warning is given if there are more host-variable-arrays than the number of columns in the
result table.

Each host-variable-array must be defined in the application program in accordance with the
rules for declaring an array. A host-variable-array is used to return the values for a column of
the result table. The number of rows to be fetched must be less than or equal to the dimension
of each of the host-variable-arrays.

An optional indicator array can be specified for a host-variable-array. It should be specified if


the SQLTYPE of any SQLVAR occurrence indicates that the column of the result table is
nullable. Additionally, if an operation may result in null values, such as an UPDATE operation
that results in a hole, is performed in the application, an indicator array should be specified.
Otherwise an error occurs if null values are encountered. The indicators are returned as small
integers.

INTO DESCRIPTOR descriptor-name


Identifies an SQLDA that must contain a valid description of zero or more host-variable-arrays
or buffers into which the values for a column of the result table are to be returned.

Before the FETCH statement is processed, you must set the following fields in the SQLDA:

SQLN to indicate the number of SQLVAR occurrences provided in the SQLDA.


SQLABC to indicate the number of bytes of storage allocated for the SQLDA.
SQLD to indicate the number of variables used in the SQLDA when processing the
statement.
SQLVAR occurrences to indicate the attributes of an element of the host-variable-
array. Within each SQLVAR representing an array:
o SQLTYPE indicates the data type of the elements of the host-variable-array.
o SQLDATA field points to the first element of the host-variable-array.
o The length fields (SQLLEN and SQLLONGLEN) are set to indicate the
maximum length of a single element of the array.
o SQLNAME - The length of SQLNAME must be set to 8, and the first two
bytes of the data portion of SQLNAME must be initialized to X'0000'. The fifth
and sixth bytes must contain a flag field and the seventh and eighth bytes
must be initialized to a binary small integer (half word) representation of the
dimension of the host-variable-array, and the corresponding indicator array, if
one is specified.
The SQLVAR entry for the number of rows must also contain a flag value. The
number of rows to be fetched must be less than or equal to the dimension of each of
the host variable arrays.

You set the SQLDATA and SQLIND pointers to the beginning of the corresponding arrays. The
SQLDA must have enough storage to contain all SQLVAR occurrences. Each SQLVAR
occurrence describes a host-variable-array or buffer into which the values for a column in the
result table are to be returned. If any column of the result table is a LOB, two SQLVAR entries
must be provided for each SQLVAR, and SQLN must be set to two times the number of
SQLVARS. SQLD must be set to a value greater than or equal to zero and less than or equal
to SQLN.

Notes
Assignment to host variables: The nth variable identified by the INTO
clause or described in the SQLDA corresponds to the nth column of the
result table of the cursor. The data type of a host variable must be
compatible with its corresponding value. If the value is numeric, the
variable must have the capacity to represent the whole part of the value.
For a datetime value, the variable must be a character string variable of a
minimum length as defined in String representations of datetime values. If
the value is null, an indicator variable must be specified.
Assignments are made in sequence through the list. Each assignment to
a variable is made according to the rules described in Language
elements. If the number of variables is less than the number of values in
the row, the SQLWARN3 field of the SQLCA is set to W. There is no
warning if there are more variables than the number of result columns. If
the value is null, an indicator variable must be provided. If an assignment
error occurs, the value is not assigned to the variable and no more values
are assigned to variables. Any values that have already been assigned to
variables remain assigned.

Normally, you use LOB locators to assign and retrieve data from LOB
columns. However, because of compatibility rules, you can also use LOB
locators to assign data to host variables with other data types. For more
information on using locators, see DB2 Application Programming and
SQL Guide.

Restrictions on using the WITH CONTINUE and CURRENT


CONTINUE clauses: When using the WITH CONTINUE clause, the DB2
system will only reserve truncated data for result set columns of the
BLOB, CLOB, DBCLOB, or XML data type, and only when the output host
variable data type is the appropriate LOB data type.

If an application uses FETCH WITH CONTINUE, and truncated data


remains after the FETCH operation, the application cannot perform any
intervening operation on that cursor before performing the FETCH
CURRENT CONTINUE. If intervening operations on that cursor are
performed, the truncated data is lost.

FETCH CURRENT CONTINUE is not supported with multi-row fetch.


Also, FETCH CURRENT CONTINUE is not supported for non-LOB and
non-XML columns that have been truncated. If truncation occurs for these
non-LOB and non-XML columns, the truncated data will be discarded as
usual.

Result column evaluation considerations: If an error occurs as the


result of an arithmetic expression in the SELECT list of an outer SELECT
statement (division by zero, or overflow) or a numeric conversion error
occurs, the result is the null value. As in any other case of a null value, an
indicator variable must be provided and the main variable is unchanged.
In this case, however, the indicator variable is set to -2. Processing of the
statement continues as if the error had not occurred. (However, this error
causes a positive SQLCODE.) If you do not provide an indicator variable,
a negative value is returned in the SQLCODE field of the SQLCA.
Processing of the statement terminates when the error is encountered. No
value is assigned to the host variable or to later variables, though any
values that have already been assigned to variables remain assigned.

If the specified host variable is not large enough to contain the result, a
warning is returned and W is assigned to SQLWARN1 in the SQLCA. The
actual length of the result is returned in the indicator variable associated
with the host-variable, if an indicator is provided. It is possible that a
warning may not be returned on a FETCH operation. This occurs as a
result of optimizations, such as the use of system temporary tables or
blocking. It is also possible that the returned warning applies to a
previously fetched row. When a datetime value is returned, the length of
the variable must be large enough to store the complete value. Otherwise,
a warning or an error is returned.
Cursor positioning: An open cursor has three possible positions:

Before a row
On a row or rowset
After the last row

When a scrollable or non-scrollable cursor is opened, it is positioned


before the first row in the result table. If a cursor is on a row, that row is
called the current row of the cursor. If a cursor is on a rowset, the rows
are called the current rowset of the cursor.

A cursor referred to in an UPDATE or DELETE statement must be


positioned on a row or rowset. A cursor can only be on a row or rowset as
a result of a FETCH statement.

If the cursor was declared SENSITIVE STATIC SCROLL, a row may be a


hole, from which no values may be fetched, updated, or deleted. Holes do
not exist with sensitive dynamic cursors because there is no temporary
result table. For information about holes in the result table of a cursor, see
DB2 Application Programming and SQL Guide.

For scrollable cursors, the cursor position after an error varies depending
on the type of error:

When an operation is attempted against an update or delete hole,


or when an update or delete hole is detected, the cursor is
positioned on the hole.
When a FETCH operation is attempted past the end of file, the
cursor is positioned after the last row.
When a FETCH operation is attempted before the beginning of
file, the cursor is positioned before the first row.
When an error causes the cursor position to be invalid such as
when a single row positioned update or positioned delete error
occurs that causes a rollback, the cursor is closed.

Cursor position after exception condition: If an error occurs during the


execution of a fetch operation, the position of the cursor and the result of
any later fetch is unpredictable. It is possible for an error to occur that
makes the position of the cursor invalid, in which case the cursor is
closed.

If an individual fetch operation specifies a destination that is outside the


range of the cursor, a warning is issued (except for FETCH BEFORE or
FETCH AFTER), the cursor is positioned before or after the result table,
and values are not assigned to host variables.

Concurrency and scrollability: The current row of a cursor cannot be


updated or deleted by another application process if it is locked. Unless it
is already locked because it was inserted or updated by the application
process during the current unit of work, the current row of a cursor is not
locked if:

The isolation level is UR, or


The isolation level is CS, and
o The result table of the cursor is read-only
o The bind option CURRENTDATA(NO) is in effect

A dynamic scrollable cursor is useful when it is more important to the


application to see updated rows and newly inserted rows and there is no
need to see deleted rows. The isolation level of CS should be used for
maximum concurrency with dynamic scrollable cursors. Specifying an
isolation level of RR or RS severely restricts the update of the table, thus
defeating the purpose of a SENSITIVE DYNAMIC scrollable cursor. If the
application needs a constant result table, a SENSITIVE STATIC scrollable
cursor with an isolation level of CS should be used.

Sensitivity of SENSITIVE STATIC SCROLL cursors to database


changes: When SENSITIVE STATIC SCROLL has been declared, the
following rules apply:

For the result of an update operation to be visible within a cursor


after "open," the update operation must be a positioned update
executed against the cursor, or a FETCH SENSITIVE in a
STATIC cursor must be executed against a row which has been
updated by some other means (that is, a searched update,
committed updates of others, or an update with another cursor in
the same process).
Another process can update the base table of the SELECT
statement so that the current values no longer satisfy the
WHERE clause. In this case, an "update hole" effectively exists
during the time the values in the base table do not satisfy the
WHERE clause, and the row is no longer accessible through the
cursor. When an attempt is made to fetch a row that has been
identified as an update hole, no values are returned, and a
warning is issued.

Under SENSITIVE STATIC SCROLL cursors, update holes are


only identified during positioned update, positioned delete, and
FETCH SENSITIVE operations. Each positioned update,
positioned delete, and FETCH SENSITIVE operation does the
necessary tests to determine if an update hole exists.

For the result of a delete operation to be visible within a


SENSITIVE STATIC SCROLL cursor, the delete operation must
be a positioned delete executed against the cursor or a FETCH
SENSITIVE in a STATIC cursor must be executed against a row
that has been deleted by some other means (that is, a searched
delete, committed deletes of others, or a delete with another
cursor in the same process).
Another process, or the even the same process, may delete a
row in the base table of the SELECT statement so that a row of
the cursor no longer has a corresponding row in the base table.
In this case, a "delete hole" effectively exists, and that row is no
longer accessible through the cursor. When an attempt is made
to fetch a row that has been identified as a delete hole, no values
are returned, and a warning is issued.

Under SENSITIVE STATIC SCROLL cursors, delete holes are


identified during positioned update, positioned delete, and
FETCH SENSITIVE operations.
Inserts into the base table or tables of SENSITIVE STATIC
SCROLL cursors are not seen after the cursor is opened.

LOB locators: When information is retrieved into LOB locators and it is


not necessary to retain the locator across FETCH statements, it is a good
practice to issue a FREE LOCATOR statement before issuing another
FETCH statement because locator resources are limited.

Isolation level considerations: The isolation level of the statement


(specified implicitly or explicitly) can affect the result of a rowset-
positioned FETCH statement. This is possible when changes are made to
the tables underlying the cursor when isolation level UR is used with a
dynamic scrollable cursor, or with other isolation levels when rows have
been added by the application fetching from the cursor. These situations
can occur with the following fetch orientations:
PRIOR ROWSET
With a dynamic scrollable cursor and isolation level UR, the content of a prior rowset can be
affected by other activity within the table. It is possible that a row that previously qualified for
the cursor, and was included as a member of the "prior" rowset, has since been deleted or
modified before it is actually returned as part of the rowset for the current statement. To avoid
this behavior, use an isolation level other than UR.
CURRENT ROWSET
With a dynamic scrollable cursor, additional rows can be added between rows that form the
rowset that was returned to the user. With isolation level RR, these rows can only be added by
the application fetching from the cursor. For isolation levels other than RR, other applications
can insert rows that can affect the results of a subsequent FETCH CURRENT ROWSET. To
avoid this behavior, use a static scrollable cursor instead of a dynamic scrollable cursor.
LAST ROWSET
With a dynamic scrollable cursor and isolation level UR, the content of the last rowset can be
affected by other activity within the table. It is possible that a row that previously qualified for
the cursor, and was included as a member of the "last" rowset, has since been deleted or
modified before it is actually returned as part of the rowset for the current statement. To avoid
this behavior, use an isolation level other than UR.
ROWSET STARTING AT RELATIVE -n (where -n is a negative
number)
With a dynamic scrollable cursor and isolation level UR, the content of a prior rowset can be
affected by other activity within the table. It is possible that a row that previously qualified for
the cursor, and was included as a member of the "prior" rowset, has since been deleted or
modified before it is actually returned as part of the rowset for the current statement. To avoid
this behavior, use an isolation level other than UR.

Row positioned and rowset positioned FETCH statement


interaction: Table 6 demonstrates the interaction between
row positioned and rowset positioned FETCH statements. The
table is based on the following assumptions:

TABLE T1 has 15 rows


CURSOR CS1 is declared as follows:
DECLARE CS1 SCROLL CURSOR WITH ROWSET
POSITIONING FOR
SELECT * FROM T1;
An OPEN CURSOR statement has been
successfully executed for CURSOR CS1 and
the FETCH statements in the table are
executed in the order that they appear in the
table.
Table 6. Interaction between row positioned and rowset positioned FETCH statement

FETCH Statement Cursor Position

FETCH FIRST Cursor is positioned on row 1.

FETCH FIRST ROWSET Cursor is positioned on a rowset of size 1, con


row 1.

FETCH FIRST ROWSET FOR 5 Cursor is positioned on a rowset of size 5, con


ROWS rows 1, 2, 3, 4, and 5.

FETCH CURRENT ROWSET Cursor is positioned on a rowset of size 5, con


rows 1, 2, 3, 4, and 5.

FETCH CURRENT Cursor is positioned on row 1

FETCH FIRST ROWSET FOR 5 Cursor is positioned on a rowset of size 5, con


ROWS rows 1, 2, 3, 4, and 5.

FETCH or FETCH NEXT Cursor is positioned on row 2.

FETCH NEXT ROWSET Cursor is positioned on a rowset of size 1, con


row 3.

FETCH NEXT ROWSET FOR 3 Cursor is positioned on a rowset of size 3, con


ROWS rows 4,5, and 6.

FETCH NEXT ROWSET Cursor is positioned on a rowset of size 3, con


rows 7,8, and 9.

FETCH LAST Cursor is positioned on row 15.

FETCH LAST ROWSET FOR 2 Cursor is positioned on a rowset of size 2, con


ROWS rows 14 and 15.

FETCH PRIOR ROWSET Cursor is positioned on a rowset of size 2, con


rows 12 and 13.

FETCH ABSOLUTE 2 Cursor is positioned on row 2.


Table 6. Interaction between row positioned and rowset positioned FETCH statement

FETCH Statement Cursor Position

FETCH ROWSET STARTING AT Cursor is positioned on a rowset of size 3, con


ABSOLUTE 2 FOR 3 ROWS rows 2, 3, and 4.

FETCH RELATIVE 2 Cursor is positioned on row 4.

FETCH ROWSET STARTING AT Cursor is positioned on a rowset of size 4, con


ABSOLUTE 2 FOR 4 ROWS rows 2, 3, 4, and 5.

FETCH RELATIVE -1 Cursor is positioned on row 1.

FETCH ROWSET STARTING AT Cursor is positioned on a rowset of size 2, con


ABSOLUTE 3 FOR 2 ROWS rows 3 and 4.

FETCH ROWSET STARTING AT Cursor is positioned on a rowset of size 2, con


RELATIVE 4 rows 7 and 8.

FETCH PRIOR Cursor is positioned on row 6.

FETCH ROWSET STARTING AT Cursor is positioned on a rowset of size 3, con


ABSOLUTE 13 FOR 5 ROWS rows 13, 14, and 15.

FETCH FIRST ROWSET Cursor is positioned on a rowset of size 5, con


rows 1, 2, 3, 4, and 5.
Note: Even though the previous FETCH state
returned only 3 rows because EOF was encou
DB2 will remember that 5 rows were requeste
previous FETCH statement.

Considerations for using the FOR n ROWS clause with


the FETCH FIRST n ROWS ONLY clause: A clause
specifying the desired number of rows can be specified in the
SELECT statement of a cursor or the FETCH statement for a
cursor, or both. However, these clauses have different effects:

In the SELECT statement, a FETCH FIRST n ROWS


ONLY clause controls the maximum number of rows
that can be accessed with the cursor. When a FETCH
statement attempts to retrieve a row beyond the
number specified in the FETCH FIRST n ROWS
ONLY clause of the SELECT statement, an end-of-
data condition occurs.
In a FETCH statement, a FOR n ROWS clause
controls the number of rows that are returned for a
single FETCH statement.

Both of these clauses can be specified.

Diagnostics information for rowset positioned FETCH


statements: A single FETCH statement from a rowset cursor
might encounter zero, one, or more conditions. If the current
cursor position is not valid for the fetch orientation, a warning
occurs and the statement terminates. If a warning or non-
terminating error (such as a bind out error) occurs during the
fetch of a row, processing continues. In this case, a summary
message is returned for the FETCH statement, and additional
information about each fetched row is available with the GET
DIAGNOSTICS statement. Use the GET DIAGNOSTICS
statement to obtain information about all of the conditions that
are encountered for one of these FETCH statements. See
GET DIAGNOSTICS for more information.

The SQLCA returns some information about errors and


warnings that are found while fetching from a rowset cursor.
Processing stops when the end of data is encountered, or
when a terminating condition occurs. After each FETCH
statement from a rowset cursor, information is returned to the
program through the SQLCA. The SQLCA is set as follows:

SQLCODE contains the SQLCODE.


SQLSTATE contains the SQLSTATE.
SQLERRD1 and SQLERRD2 contain the number of
rows of the result table if the cursor is positioned on
the last row of the result table.
SQLERRD3 contains the actual number of rows
returned. If SQLERRD3 is less than the number of
rows requested, an error or end-of-data condition
occurred.
SQLWARN flags are set to represent all the warnings
that were accumulated while processing the FETCH
statement.

Consider the following examples, where 10 rows are fetched


with a single FETCH statement.

Example 1: Assume that an error is detected on the


5th row. SQLERRD3 is set to 4 for the 4 returned
rows, SQLSTATE is set to 22537, and SQLCODE is
set to -354. This information is also available from the
GET DIAGNOSTICS statement (the information that
is returned is generated from connected server, which
may differ across different servers). For example:
GET DIAGNOSTICS :num_rows =
ROW_COUNT, :num_cond = NUMBER;
-- Results of the statement:
-- num_rows = 4 and num_cond = 1 (1
condition)
GET DIAGNOSTICS CONDITION 1 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = DB2_RETURNED_SQLCODE,
:row_num = DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 22537, sqlcode = -354, and
row_num = 5
Example 2: Assume that an end-of-data condition is
detected on the 6th row and that the cursor does not
have immediate sensitivity to updates. SQLERRD3 is
set to 5 for the 5 returned rows, SQLSTATE is set to
02000, and SQLCODE is set to +100. This
information is also available from the GET
DIAGNOSTICS statement. For example:
GET DIAGNOSTICS :num_rows =
ROW_COUNT, :num_cond = NUMBER;
-- Results of the statement:
-- num_rows = 5 and num_cond = 1 (1
condition)
GET DIAGNOSTICS CONDITION 1 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = DB2_RETURNED_SQLCODE,
:row_num = DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 02000, sqlcode = 100, and
row_num = 6
Example 3: Assume that an bind out error condition is
detected on the 5th row, the condition is recorded,
and processing continues. Also, assume that an end-
of-data condition is detected on the 8th row.
SQLERRD3 is set to 7 for the 7 returned rows,
SQLSTATE is set to 02000, and SQLCODE is set to
+100. Processing to complete the FETCH statement
is performed, and the bind out error that occurred is
noted. An additional SQLCODE is recorded for the
bind out error. SQLCODE is set to 354, and
SQLSTATE is set to 01668. Use the GET
DIAGNOSTICS statement to determine what went on.
For example:
GET DIAGNOSTICS :num_rows =
ROW_COUNT, :num_cond = NUMBER;
-- Results of the statement:
-- num_rows = 7 and num_cond = 3 (3
conditions)
GET DIAGNOSTICS CONDITION 1 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = RETURNED_SQLCODE, :row_num =
DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 01668, sqlcode = -354, and
row_num = 0
GET DIAGNOSTICS CONDITION 2 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = RETURNED_SQLCODE, :row_num =
DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 02000, sqlcode = 100, and
row_num = 0
GET DIAGNOSTICS CONDITION 3 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = RETURNED_SQLCODE, :row_num =
DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 22003, sqlcode = -302, and
row_num = 5

In some cases, DB2 returns a warning if indicator variables


are provided, or an error if indicator variables are not provided.
These errors can be thought of as data mapping errors that
result in a warning if indicator variables are provided.

If indicator variables are provided, DB2 returns all


rows to the user, marking the errors in the indicator
variables. The SQLCODE and SQLSTATE contain the
warning from the last data mapping error. The GET
DIAGNOSTICS statement can be used to retrieve
information about all the data mapping errors that
have occurred.
If some or no indicator variables are provided, all rows
are returned as above until the first data mapping
error that does not have indicator variables is
detected. The rows successfully fetched are returned
and the SQLSTATE, SQLCODE, and SQLWARN flags
are set, if necessary. (The SQLCODE may be 0 or a
positive value).

It is possible, if a data mapping error occurs, for the


positioning of the cursor to be successful. In this case, the
cursor is positioned on the rowset that encountered the data
mapping error.

Consider the following examples, which try to fetch 10 rows


with a single FETCH statement.

Example 1: Assume that indicators have been


provided for values returned for column 1, but not for
column 2. The 5th row has a data mapping error
(+802) for column 1, and the 7th row has a data
mapping error for column 2 (-802 is returned because
an indicator was not provided for column 2).
SQLERRD3 is set to 6 for the 6 returned rows,
SQLSTATE and SQLCODE are set to the error from
the 7th row fetched. The indicator variable for the 5th
row column 1 indicates that a data mapping error was
found. This information is also available from the GET
DIAGNOSTICS statement, for example:
GET DIAGNOSTICS :num_rows =
ROW_COUNT, :num_cond = NUMBER;
-- Results of the statement:
-- num_rows = 6 and num_cond = 2 (2
conditions)
GET DIAGNOSTICS CONDITION 1 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = DB2_RETURNED_SQLCODE,
:row_num = DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 01519, sqlcode = +802, and
row_num = 5
GET DIAGNOSTICS CONDITION 2 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = DB2_RETURNED_SQLCODE,
:row_num = DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 22003, sqlcode = -802, and
row_num = 7
The resulting cursor position is unknown.
Example 2: Assume that null indicators are provided,
that rows 3 and 5 are holes, and that data exists for
the other requested rows. SQLERRD3 is set to 10 to
reflect that 10 fetches were completed and that
information has been returned for the 10 requested
rows. Eight rows actually contain data. For two rows,
indicator variables are set to indicate no data was
returned for those rows. SQLSTATE is set to 02502,
SQLCODE is set to +222, and all null indicators for
rows 3 and 5 are set to -3 to indicate that a hole was
detected. This information is also available from the
GET DIAGNOSTICS statement, for example:
GET DIAGNOSTICS :num_rows =
ROW_COUNT, :num_cond = NUMBER;
-- Results of the statement:
-- num_rows = 10 and num_cond = 2 (2
conditions)
GET DIAGNOSTICS CONDITION 1 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = DB2_RETURNED_SQLCODE,
:row_num = DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 02502, sqlcode = +222, and
row_num = 3
GET DIAGNOSTICS CONDITION 2 :sqlstate =
RETURNED_SQLSTATE,
:sqlcode = DB2_RETURNED_SQLCODE,
:row_num = DB2_ROW_NUMBER;
-- Results of the statement:
-- sqlstate = 02502, sqlcode = +222, and
row_num = 5
If a null indicator was not provided for any variable in
a row that was a hole, an error occurs.
SQLCA usage summary: For multiple-row-fetch, the fields of the SQLCA are set as follows:

Condition Action: Resulting Values Stored in the


Fields

Errors Data SQLSTATE SQLCODE SQL

No1 Return all requested rows 00000 0 Numbe


request
Condition Action: Resulting Values Stored in the
Fields

Errors Data SQLSTATE SQLCODE SQL

No1 Return data for subset of 02000 +100 Numbe


requested rows, end of data rows

No1 Return all requested rows sqlstate(2) sqlcode(2) Numbe


request

Yes1 Return successfully fetched sqlstate(3) sqlcode(3) Numbe


rows

Yes1 Return successfully fetched sqlstate(4) sqlcode(4) Numbe


rows

Notes:
1. SQLWARN flags may be set in all cases, even if there are no other warnings
errors indicated. The warning flags are an accumulation of all warning flags s
while processing the multiple-row-fetch.
2. sqlcode is the last positive SQLCODE, and sqlstate is the corresponding
SQLSTATE value.
3. Database Server detected error. sqlcode is the first negative SQLCODE
encountered, sqlstate is the corresponding SQLSTATE value.
4. Client detected error. sqlcode is the first negative SQLCODE encountered, s
is one of the following SQLSTATEs: 22002, 22008, 22509, 22518, or 55021.

Providing indicator variables for error conditions: If an


error occurs as the result of an arithmetic expression in the
SELECT list of an outer SELECT statement (division by zero
or overflow) or a numeric conversion error occurs, the result is
the null value. As in any other case of a null value, an indicator
variable must be provided and the main variable is
unchanged. In this case, however, the indicator variable is set
to -2. Processing of the statement continues as if the error had
not occurred. (However, this error causes a positive
SQLCODE.)

If you do not provide an indicator variable, a negative value is


returned in the SQLCODE field of the SQLCA. Processing of
the statement terminates when the error is encountered. No
value is assigned to the host variable or to later variables,
though any values that have already been assigned to
variables remain assigned. Additionally, a -3 is returned in all
indicators provided by the application when a hole was
detected for the row on a rowset positioned FETCH, and
values were not returned for the row. Processing of the
statement terminates if a hole is detected and at least one
indicator variable was not provided by the application.
Alternative syntax and synonyms: USING DESCRIPTOR
can be specified as a synonym for INTO DESCRIPTOR.

Example
Example 1: The FETCH statement fetches the results of the SELECT statement into the application
program variables DNUM, DNAME, and MNUM. When no more rows remain to be fetched, the not
found condition is returned.
EXEC SQL DECLARE C1 CURSOR FOR
SELECT DEPTNO, DEPTNAME, MGRNO FROM DSN8910.DEPT
WHERE ADMRDEPT = 'A00';
EXEC SQL OPEN C1;
DO WHILE (SQLCODE = 0);
EXEC SQL FETCH C1 INTO :DNUM, :DNAME, :MNUM;
END;
EXEC SQL CLOSE C1;

Example 2: For an example of FETCH statements with a dynamic scrollable cursor, see Example 8.

Example 3: Fetch the last 5 rows of the result table C1 using cursor C1:
FETCH ROWSET STARTING AT ABSOLUTE -5
FROM C1 FOR 5 ROWS INTO DESCRIPTOR :MYDESCR;
Example 4: Fetch 6 rows starting at row 10 for cursor CURS1, and fetch the data into three host-
variable-arrays:
FETCH ROWSET STARTING AT ABSOLUTE 10
FROM CURS1 FOR 6 ROWS
INTO :hav1, :hva2, :hva3;
Alternatively, a descriptor could have been specified in an INTO DESCRIPTOR clause where the
information in the SQLDA reflects the data types of the host-variable-arrays:
FETCH ROWSET STARTING AT ABSOLUTE 10
FROM CURS1 FOR 6 ROWS
INTO DESCRIPTOR :MYDESCR;

Das könnte Ihnen auch gefallen