Retrieving Multiple Tuples
with Embedded SQL Using Cursors
We can think of a cursor as a
pointer that points to a single tuple
(row) from the result of a query that
retrieves multiple tuples. The cursor is declared when the SQL query command is
declared in the program. Later in the program, an OPEN CURSOR command fetches the query result from the database and sets the cursor
to a position before the first row
in the result of the query. This becomes the current row for the cursor. Subsequently, FETCH commands are issued in the program; each FETCH moves the
cursor to the
next row in the result of the query, making it the cur-rent row and copying its
attribute values into the C (host language) program variables specified in the
FETCH command by an INTO clause. The cursor variable is
basically an iterator that iterates
(loops) over the tuples in the query result—one tuple at a time.
To determine when all the tuples in the result of the query have been
processed, the communication variable SQLCODE (or,
alternatively, SQLSTATE) is checked. If a FETCH command is issued that results in
moving the cursor past the last tuple in the result of
the query, a positive value (SQLCODE > 0) is returned in SQLCODE, indicating that no data (tuple) was found (or the string ‘02000’ is
returned in SQLSTATE). The programmer uses this to terminate a loop over the tuples in the query result. In general, numerous cursors can be opened at the same
time. A command is issued to indicate that we are done with processing the
result of the query associated with that cursor.
An example of using cursors to process a query result with multiple
records is shown in Figure 13.3, where a cursor called EMP is declared in line 4. The EMP cursor
is associated with the SQL query declared in lines 5 through 6, but the query
is not executed until the OPEN EMP command (line 8) is processed.
The OPEN <cursor name> command executes the query and fetches its result
as a table into the program workspace, where the program can loop through the
individual rows (tuples) by subsequent FETCH
<cursor name> commands (line 9). We assume that appropriate C program
variables have been declared as in Figure 13.1. The program segment in E2 reads
(inputs) a department name (line 0), retrieves the matching department number
from the database (lines 1 to 3), and then retrieves the employees who work in
that department via the declared EMP cursor.
A loop (lines 10 to 18) iterates over each record in the query result, one at a
time, and prints the employee name. The program then reads (inputs) a raise
amount for that employee (line 12) and updates the employee’s salary in the
database by the raise amount that was provided (lines 14 to 16).
This example also illustrates how the programmer can update database records. When a cursor
is defined for rows that are to be modified (updated), we must add
Figure 13.3
Program segment E2, a C
program segment that uses cursors with embedded SQL for update purposes.
//Program
Segment E2:
prompt("Enter
the Department Name: ", dname) ;
EXEC
SQL
select
Dnumber into :dnumber
from
DEPARTMENT where Dname = :dname ;
EXEC
SQL DECLARE EMP CURSOR FOR
select
Ssn, Fname, Minit, Lname, Salary
from
EMPLOYEE where Dno = :dnumber
FOR
UPDATE OF Salary ;
EXEC
SQL OPEN EMP ;
EXEC
SQL FETCH from EMP into :ssn, :fname, :minit, :lname, :salary ;
while
(SQLCODE == 0) {
printf("Employee
name is:", Fname, Minit, Lname) ;
prompt("Enter
the raise amount: ", raise) ;
EXEC
SQL
update
EMPLOYEE
set
Salary = Salary + :raise
where
CURRENT OF EMP ;
EXEC
SQL FETCH from EMP into :ssn, :fname, :minit, :lname, :salary ;
}
EXEC
SQL CLOSE EMP ;
the clause FOR UPDATE OF in the cursor declaration and list the names of any attributes that
will be updated by the program. This is illustrated in line 7 of code segment
E2. If rows are to be deleted, the
keywords FOR
UPDATE must be added without specifying
any attributes. In the embedded UPDATE (or DELETE) command, the condition WHERE CURRENT OF<cursor
name> specifies that the cur-rent tuple referenced by the cursor is the one
to be updated (or deleted), as in line 16 of E2.
Notice that declaring a cursor
and associating it with a query (lines 4 through 7 in E2) does not execute the
query; the query is executed only when the OPEN
<cursor name> command (line 8) is executed. Also notice that there is no
need to include the FOR UPDATE OF clause in line 7 of E2 if the
results of the query are to be used for
retrieval purposes only (no update or
delete).
General Options for a Cursor Declaration. Several
options can be specified when declaring a cursor. The
general form of a cursor declaration is as follows:
DECLARE <cursor name> [ INSENSITIVE ] [
SCROLL ] CURSOR
[ WITH HOLD ] FOR <query specification> [ ORDER BY <ordering specification> ]
[ FOR READ ONLY | FOR UPDATE [ OF <attribute list> ] ] ;
We already briefly discussed the
options listed in the last line. The default is that the query is for retrieval
purposes (FOR
READ ONLY). If some of the tuples in the
query result are to be updated, we need to specify FOR UPDATE OF <attribute list> and list the attributes that may be updated. If
some tuples are to be deleted, we need to specify FOR UPDATE without any attributes listed.
When the optional keyword SCROLL is specified in a cursor declaration, it is possible to position the
cursor in other ways than for purely sequential access. A fetch orientation can be
added to the FETCH command, whose value can be one of
NEXT, PRIOR,
FIRST, LAST, ABSOLUTE i, and RELATIVE i. In the latter two commands, i
must evaluate to an integer value that specifies an
absolute tuple position within the query result (for ABSOLUTE i), or a tuple position
relative to the current cursor position (for RELATIVE i). The default fetch orientation, which
we used in our examples, is NEXT. The fetch orientation allows
the programmer to move the cursor around the tuples in the query result with
greater flexibility, providing random access by position or access in reverse
order. When SCROLL is specified on the cursor, the general form of a FETCH command is as follows, with the parts in square brackets being
optional:
FETCH [ [ <fetch orientation> ] FROM ] <cursor name> INTO <fetch target list> ;
The ORDER BY clause orders the tuples so that the FETCH command
will fetch them in the specified order. It is specified in a similar manner to
the corresponding clause for SQL queries (see Section 4.3.6). The last two
options when declaring a cursor (INSENSITIVE and WITH HOLD) refer to transaction characteristics of database pro-grams, which we
will discuss in Chapter 21.
Related Topics
Privacy Policy, Terms and Conditions, DMCA Policy and Compliant
Copyright © 2018-2024 BrainKart.com; All Rights Reserved. Developed by Therithal info, Chennai.