June 15, 2002 Volume 3 Issue 05
DB2 and You
A Newsletter to give tips, answer questions and expand our knowledge
definition fits the DB2 usage perfectly.
What do cursors mean to DB2? When
Tip of the Month you execute SQL SELECT statements,
DB2 returns the entire set of rows (called
the answer set) that satisfy the SELECT.
A typical program would likely suffer if it
Cursors! Foiled No More had to deal with the entire answer set
Willie Favero 1 (which could contain thousands, if not
tens of thousands, of rows) returned from
They're necessary in nearly every DB2 a SELECT. All the returned rows have to
program. But with their one-directional be placed somewhere; programmers
abilities, cursors could seem a formidable wanted a mechanism that allowed
foe. Arriving to save the day? New, programs to process all that data without
scrollable cursors in DB2 UDB for z/OS bringing it into working storage.
and OS/390. Enter the cursor. Cursors allow the
Have you ever driven a car? Ever use program to point to a single row within
reverse? Dumb question, isn't it? Driving the result, retrieve and process that row,
would be a logistical nightmare if you and then move on to the next row if
could only drive forward. What about necessary. But before v.7, they could
using a phone book? Can you image only move on to the next row, they
having to go back to the first page of the couldn't return or move backward.
phone book to start your search over Before you can appreciate what an
again because you passed your listing or advance this feature is, you have to
wanted to read the listing again? understand the limitations imposed by the
Although these examples sound far- original cursors.
fetched, they illustrate the challenge that
faced application developers every time
IN THE BEGINNING
they wrote a program that used cursors. DB2 has been around a fairly long time
Fortunately, that method of programming — some 18 years. In all that time, the
will soon be a distant memory, thanks to SQL provided with DB2 for navigating
the scrollable cursor feature of DB2 data from an application program really
Universal Database (DB2 UDB) for z/OS hasn't changed. If you have more than
and OS/390 Version 7. one row to read, you use a cursor.
Merriam-Webster's Collegiate Dictionary
defines a cursor as "a movable pointer
used to mark a position." And that
1 Staff Development
2 PeRFect PRF
From DB2 Magazine 2nd Quarter, 2002
3 Fun Stuff
For most application developers, using a cursor name itself is simply an SQL long
cursor in a program is just a way of life — identifier (18 or less characters) unique
sometimes a difficult way of life. As within that program. WITH HOLD and
required since DB2's introduction, an WITH RETURN give the cursor special
application program must first declare a characteristics. WITH HOLD prevents the
cursor. Doing so amounts to defining cursor from being closed by a commit,
what the SELECT statement should look thus maintaining the cursor's position.
like to generate a set of rows that the WITH RETURN is used by a DECLARE
program could then process. After CURSOR in a stored procedure to make
declaring the cursor, the next step is to that cursor's answer set available to the
open that cursor in the processing part of program calling the stored procedure.
the program. The open cursor actually WITH RETURN, introduced with v.5,
executes the SELECT statement, asking made stored procedures really useful.
DB2 to prepare a set of rows as an
The answer set for the declared cursor is
answer set for additional processing.
created when the cursor is opened using
With the cursor opened and an answer
the SQL OPEN CURSOR statement.
set created, the program can fetch rows
OPEN CURSOR causes DB2 to execute
from the answer set.
the SELECT in the DECLARE statement.
But here is where the problems began. Of course, the OPEN may not always
SQL FETCH statements could only fetch create an answer set; it may just allow
forward, retrieving the next row from the the FETCH to retrieve rows directly from
answer set and returning the row to the the base table. (If an answer set is
program for processing. Any need to created, all the rows that satisfy the
reread the current row or (heaven forbid) SELECT are read before the OPEN
go back and get a previously read row completes. If no answer set is necessary,
meant you were out of luck. If you hadn't the rows are read directly from the table
saved the answer set somehow, the as needed. Performance is better when
program would have to close the cursor, reading directly from the table.) Any host
reopen it, and start the fetch process all variables specified in the DECLARE
over. statement's SELECT would have to be
initialized prior to issuing the open.
WORKING WITH CURSORS
The SQL FETCH CURSOR statement
makes a row available to a program.
Using cursors in a program requires Prior to v.7, the FETCH would always
adding four SQL statements: DECLARE, retrieve the next row until no more rows
OPEN, FETCH, and CLOSE CURSOR. were available. On the FETCH after
The DECLARE CURSOR statement reading the last row, DB2 would return a
describes how the set of rows (the +100 SQLCODE to the application to let
answer set) will be created, identifies the the program know that there were no
name of the cursor associated to that more rows to process. But because it
answer set, and describes any special only allowed you to fetch forward, DB2
cursor characteristics. Creating an couldn't help if you needed to reread the
answer set is simple. The SQL SELECT current row or a previous row (for
statement coded within the DECLARE example, to make sure the value hasn't
identifies the tables and rows that will be changed before updating a column).
included in the answer set. The SELECT The CLOSE CURSOR statement closes
can be as simple or complex as the the cursors when processing is complete.
programmer wants. There are no If a close isn't issued, the cursor remains
restrictions. It can be dynamic or static open until the program terminates, which
SQL and can contain host variables. The could create locking implications in some
programmer needs to decide if the cursor situations.
will be updateable or read-only. The
USING SCROLLABLE CURSORS declared temporary table for retrieving
rows and never reuses the base table.
DB2 v.7 alleviates the fetching forward
limitation by implementing scrollable Only updates and deletes are reflected in
cursors. Scrollable cursors give the answer set of a sensitive cursor. If an
application programs the ability to scroll update or delete is processed against the
forward, backward, or to a relative or table and the cursor is defined as
absolute position anywhere in the answer sensitive, the change is reflected in the
set. Originally written up in the SQL3 answer set as an update or delete hole.
ANSI Standard and later moved into the Inserts are never reflected in the answer
SQL99 Standard, the definition of how set. These holes present special
scrollable cursors should work has been processing challenges for programmers:
around for a number of years. Most of the They will need to add extra code to their
standard's definition is included in v.7. applications to test the SQLCODE
returned. This test avoids processing a
In order to give the FETCH statement hole.
scrolling capabilities, you add the new
keyword SCROLL to the DECLARE In addition to the FETCH improvements
CURSOR definition. Before you can I've described, the standard allows for
change all your applications, though, you eight more methods to manipulate a
need to perform some planning and prep cursor, plus the original NEXT. Here's an
work. introduction to each:
Scrollable cursors require declared global • NEXT, the default, should be the most
temporary tables. So you need to create familiar cursor movement as it's been
a temporary database specifying the AS used since DB2's beginnings. NEXT
TEMP keyword. AS TEMP tells DB2 that positions the cursor on the next row
only declared temporary tables can use relative to its current position in the
this temporary database. Within this answer set. If there are no more rows
database, tablespaces of adequate size available, a +100 is returned to the
and number must be defined. These program.
tablespaces are used to maintain the • PRIOR moves the cursor to the previous
cursor's answer sets. Make sure you row relative to the cursor's current position
create tablespaces large enough to and retrieves the row. An error occurs if it
handle the answer sets your scrollable positions the cursor before the first row
cursors are going to create. The declared and a warning occurs if it attempts to
temporary table is only accessible by the position the cursor on a hole.
cursor that created it and is dropped
when the cursor is closed. The DBA or • FIRST positions the cursor on the first row
programmer must define the temporary in the answer set and then retrieves that
database prior to implementing scrollable row. If the first row no longer exists and
cursors. In a data-sharing environment, a there is now a hole, a message is returned
temp workspace must be defined to each to the application and no values are
data-sharing member. assigned.
After you define the temporary database • LAST positions the cursor on the last row
and update the DECLARE CURSOR with in the answer set and then retrieves that
the keyword SCROLL, you're ready to row. If the last row no longer exists and
scroll. When specifying SCROLL, you there is now a hole, a message is returned
have to specify SENSITIVE STATIC, or to the application and no values are
INSENSITIVE (there is no default). If you assigned.
specify SENSITIVE, changes made by • ABSOLUTE cursor positioning will move
your cursor and other cursors are visible the cursor to an absolute position (a
to your application. INSENSITIVE uses a specific row relative to the top or bottom of
the answer set depending on the plus or
minus number). The absolute position can a SELECT was successful and didn't just
be specified by a constant or a host get a SQLCODE 0.
Finally, when defining the host variables
• RELATIVE cursor positioning will move used for positioning on a FETCH
the cursor a plus or minus number of rows RELATIVE or ABSOLUTE, you probably
relative to the current position. Relative want to use integer. Although decimal
position can be specified using a constant can be used, you have to be careful to
or a host variable. specify a zero value for the decimal
portion of the number. It's difficult for DB2
• BEFORE only positions the cursor before
to move the cursor in increments of less
the first row in the results table and no
data is returned.
The CLOSE cursor statement remains
• AFTER positions the cursor after the last
unchanged when defining a scrollable
row in the answer set and no data is
cursor. However, the OPEN behaves
slightly differently. The OPEN will return,
• CURRENT may be the most exciting of via the SQLCA, whether the cursor is
all. It doesn't reposition the cursor; it scrollable or not in SQLWARN1. It will
simply returns the current row again. also return if the cursor is sensitive or
CURRENT is the same as FETCH insensitive static in SQLWARN5. This
RELATIVE 0. latter information can be useful in
applications using the open database
BE VIGILANT connectivity (ODBC) driver that need to
determine the sensitivity because the
There are a few quirks you need to be cursor has been defined as SENSITIVE.
aware of when using scrollable cursors. Also at OPEN, after all of the rows have
When executing a FETCH NEXT, been moved to the temporary table, all
PRIOR, or CURRENT and the cursor is locks are released from the base table
positioned on an update or delete hole, unless isolation-level repeatable read or
DB2 returns no values to the host read stability are specified.
variables and a warning is issued to the Another v.7 feature may come into use
program. The program must check for when working with scrollable cursors:
this warning because the FETCH leaves FETCH FIRST n ROWS ONLY. When
the cursor positioned on the hole and any added to a SELECT, this phrase allows
values in the host variables are no longer only the number of rows specified by n to
valid. be retrieved from the answer set. In other
Here's a neat feature: When issuing a words, a fixed number of rows that
FETCH LAST or AFTER or when the satisfies the WHERE predicate is
application receives a +100 from the retrieved rather than the entire answer
fetch, DB2 supplies the number of rows set. One use of this phrase would be to
in the answer set to the program via the retrieve a single row from a table without
SQLCA using the variables SQLERRD(1) using a cursor, regardless of the number
and SQLERRD(2). Of course, any host of rows in that table. However, it could
variables on the FETCH are again not also be used to limit the number of rows
updated. In both cases, the host from the answer set that must be stored
variables may contain the values from the in the temporary table.
last successful FETCH. Host variables If you decide to access scrollable cursors
should never be trusted if the FETCH from an application using ODBC or Java
returned a nonzero SQLCODE. By database connectivity (JDBC), the
externalizing the number of rows application needs to make sure that
returned, an application can validate that scrolling is available at the server it is
going to access. JDBC and ODBC make
no assumptions about SQL's capabilities. KEEPing a new table If the table-name
If using ODBC, the program should issue used with the KEEP command is not an
the getINFO() call. If using Java, the already-existing table, it is created in the
program should issue a JDBC getTYPE() default database, in its own tablespace.
call to determine if scrollable cursors are
All detail line data, including query and
form expressions, are saved into the
Right now, DB2 offers static scrolling — a table. Column names are built from the
great improvement. The next step may first 18 characters of the query field
be to add dynamic scrolling. What is the names, with underscores in place of any
difference? Dynamic scrolling works invalid characters.
directly against the table being accessed
during cursor scrolling. Static scrolling KEEPing an existing table If the table
only works against a declared temporary in your KEEP command already exists, all
table in a temp database. previously existing data is deleted. The
BEYOND THE SURFACE structure of the new data must be exactly
like that of the existing table, or an SQL
This article should give you some insight error will result, just as if you tried to
into how scrollable cursors can make insert a row of improperly formatted data
programming DB2 applications easier into a table. Your SQLID must have
while allowing the programmer more insert and delete authority for the table.
choices, flexibility, and power. In fact, you
may find that this feature alone may Accessing the table is as simple as
make it worth your while to migrate to accessing any other DB2 table. In PRF,
DB2 v.7. But this is merely an overview. on the Select Tables screen, enter your
For all the nitty-gritty details, see the DB2 SQLID next to ID>, as the table creator
v.7 Presentation Guide (SG24-6121), name. A list of tables kept under your ID
SQL Reference (SC26-9944), and will appear, and you can select the one
Application Programming and SQL Guide you need. Tables created using KEEP
(SC26-9933). And have fun scrolling! may also be accessed in SPUFI, prefaced
by the SQLID.
CCSD developers have found KEEP
PeRFect PRF handy in a few scenarios where doing all
the processing in one PRF was either not
possible or very complex.
PRF is the Platinum Report Facility, a
handy tool for creating reports from DB2 Mailing lables including a literal: Often
without writing a program. mailing labels require a literal line added,
such as “To the parent of:”. This is easily
This month, we look at the KEEP
accomplished in SQL by selecting the
command to save detail data from a
desired literal along with the address
query or report in a DB2 table, providing
columns. However, when the addresses
the ability to re-use the result data with
are in a VSAM file it is not so easy. One
other queries or at other times.
CCSD developer used KEEP to quickly
Using the KEEP Command After store the addresses from the VSAM file
running a query or report, while the into a DB2 table, then was able to select
results are on your screen, enter KEEP the literal and create the labels.
table-name. A table will be created with
Simplifying complex queries: Another
your SQLID as the owner, containing the
CCSD developer had a very complex
query results you see on the screen as
query requiring many CASE statements
rows and columns in the new table.
involving a substring of a column. By 6. Macintosh would make a car that was
breaking down the query to first create a powered by the sun, reliable, five times as
new column for the substring and fast, and twice as easy to drive, but would
KEEPing the result, then using a second only run on five percent of the roads.
query for the CASE statement, the 7. The oil, water temperature and
developer saved the time of writing a alternator warning lights would be
COBOL program to create the report. replaced by a single "general car default"
8. New seats would force everyone to
Staff Development have the same size butt.
9. The airbag system would say "Are you
sure?" before going off.
Date Topic 10. Occasionally for no reason
whatsoever, your car would lock you out
06/19/2002 Dr. Brody will and refuse to let you in until you
address the group simultaneously lifted the door handle,
06/26/2002 How to play in our turned the key, and grab hold of the radio
11. GM would require all car buyers to
also purchase a deluxe set of Rand
Fun Stuff McNally road maps (now a GM
subsidiary), even though they neither
need them nor want them. Attempting to
delete this option would immediately
If GM had developed technology like cause the car's performance to diminish
Microsoft, we would all be driving cars by 50% or more. Moreover, GM would
with the following characteristics: become a target for investigation by the
1. For no reason whatsoever your car Justice Department.
would crash twice a day. 12. Every time GM introduced a new
2. Every time they repainted the lines on model car buyers would have to learn
the road you would have to buy a new how to drive all over again because none
car. of the controls would operate in the same
manner as the old car.
3. Occasionally your car would die on the
freeway for no reason, and you would just 13. You'd press the "start" button to shut
accept this, restart and drive on. off the engine.
4. Occasionally, executing a maneuver
such as a left turn, would cause your car
to shut down and refuse to restart, in
which case you would have to reinstall
5. Only one person at a time could use
the car, unless you bought "Car95" or
"CarNT." But then you would have to buy