HP 3000 Manuals

Sequential Table Processing Commands [ ALLBASE/SQL FORTRAN Application Programming Guide ] MPE/iX 5.0 Documentation


ALLBASE/SQL FORTRAN Application Programming Guide

Sequential Table Processing Commands 

The SQL commands used for sequential table processing are:

   *   DECLARE CURSOR: defines a cursor and associates with it a query.

   *   OPEN: defines the active set.

   *   FETCH: retrieves one row of the active set into host variables;
       when a row resides in host variables it is known as the current 
       row.  When a row is current and the active set is a query result
       derived from a single table, you can use one of the following two
       commands to change the row.

   *   UPDATE WHERE CURRENT: updates the current row.

   *   DELETE WHERE CURRENT: deletes the current row.

   *   CLOSE: frees up ALLBASE/SQL intermal buffer space used to handle
       the cursor.

Refer to the ALLBASE/SQL Reference Manual for the complete syntax and
semantics of these commands.  Ensure that all the commands listed above
for any single cursor are contained within the same transaction.

The DECLARE CURSOR Command 

The DECLARE CURSOR command names a cursor and associates with it a
particular SELECT command:

          DECLARE CursorName 
                  [IN DBEFileSetName]
                  CURSOR FOR
                  SelectCommand 
                  [FOR UPDATE OF ColumnName [,ColumnName...]]

Note that the DECLARE CURSOR command has two optional clauses:

   *   The IN clause defines the DBEFileSet in which the section
       generated by the preprocessor for this command is stored.  If no
       IN clause is specified, file space in the SYSTEM DBEFileSet is
       used.

   *   The FOR UPDATE clause is used when you use the UPDATE WHERE
       CURRENT command to update a current row.  This command may offer
       the simplest way to update a current row, but it imposes certain
       restrictions on the SELECT command.  Updating a current row is
       fully discussed later in this chapter under the UPDATE WHERE
       CURRENT command.

The SELECT command for cursor declarations that do not include the FOR
UPDATE clause can consist of any of the SELECT command clauses except the
INTO clause:

          SELECT SelectList 
            FROM TableNames 
           WHERE SearchCondition1 
        GROUP BY ColumnNames 
          HAVING SearchCondition2 
        ORDER BY ColumnIdentifiers 

A SELECT command associated with a cursor does not name output host 
variables, but may name input host variables in the select list, the
WHERE clause, and the HAVING clause.  In the following example, the rows
qualifying for the query result will be those with a CountCycle matching
that specified by the user in input host variable CountCycle:

            EXEC SQL DECLARE Inventory
          1           CURSOR FOR
          2           SELECT PartNumber,
          3                  BinNumber,
          4                  QtyOnHand,
          5                  AdjustmentQty
          6             FROM PurchDB.Inventory
          7            WHERE CountCycle = :CountCycle
          8         ORDER BY BinNumber

When performing sequential table processing, the ORDER BY clause may be
useful.  In the example above, the rows in the query result will be in
order by ascending bin number to help the program user, who will be
moving from bin to bin, taking a physical inventory.

The DECLARE CURSOR command is actually a preprocessor directive.  When
the FORTRAN preprocessor parses this command, it stores a section in the
target DBEnvironment.  At runtime, the section is not executed when the
DECLARE CURSOR command is encountered, but when the OPEN command is
executed.  Because the DECLARE CURSOR command is not executed at runtime,
you do not need to perform status checking in your program following this
command.

The OPEN Command 

The OPEN command examines any input host variables and determines the
active set:

          OPEN CursorName 

The following command defines the active set associated with the cursor
defined earlier:

          EXEC SQL OPEN Inventory

You use the FETCH command to retrieve a row at a time from the active
set.

You can use the KEEP CURSOR WITH NOLOCKS option for a cursor that
involves sorting, whether through the use of a DISTINCT, GROUP BY, or
ORDER BY clause, or as the result of a union or a join operation.
However, for kept cursors involving sorting, ALLBASE/SQL does not ensure
data integrity.  See the "Programming for Performance" chapter for more
information on ensuring data integrity.

The FETCH Command 

The FETCH command defines a current row and delivers the row into output
host variables:

          FETCH CursorName INTO :OutputHostVariables 

Remember to include indicator variables when one or more columns in the
query result may contain a null value:

            EXEC SQL FETCH  Inventory
          1           INTO :PartNumber,
          2                :BinNumber,
          4                :QtyOnHand     :QtyOnHandInd,
          5                :AdjustmentQty :AdjustmentQtyInd

The first time you execute the FETCH command, the first row in the query
result is the current row.  With each subsequent execution of the FETCH
command, each succeeding row in the query result becomes current.  After
the last row in the query result has been fetched, ALLBASE/SQL sets
SQLCode to 100.  ALLBASE/SQL also sets SQLCode to 100 if no rows qualify
for the active set.  You should test for an SQLCode value of 100 after
each execution of the FETCH command to determine whether to re-execute
this command:

          SUBROUTINE GetARow
          .
          .
          OK       = 0
          NotFound = 100
          DoFetch  = .TRUE.
          DO WHILE (DoFetch)
          .
          .     The FETCH command appears here.
          .
          IF (SQLCode .EQ. OK) THEN
            CALL DisplayRow
          ELSEIF (SQLCode .EQ. NotFound) THEN
            DoFetch = .FALSE.
            CALL CloseCursor
            CALL CommitWork
          ELSE
            DoFetch = .FALSE.
            CALL SQLStatusCheck
            CALL CloseCursor
            CALL RollBackWork
          ENDIF
          END DO
          RETURN
          END

When a row is current, you can update it by using the UPDATE WHERE
CURRENT command or delete it by using the DELETE WHERE CURRENT command.

The UPDATE WHERE CURRENT Command 

This command can be used to update the current row when the SELECT
command associated with the cursor does not contain one of the following:

   *   DISTINCT clause in the select list.
   *   Aggregate function in the select list.
   *   FROM clause with more than one table.
   *   ORDER BY clause.
   *   GROUP BY clause.

The UPDATE WHERE CURRENT command identifies the active set to be updated
by naming the cursor and the column(s) to be updated:

          UPDATE TableName 
             SET ColumnName = ColumnValue 
                 [,...]
           WHERE CURRENT OF CursorName 

Any columns you name in this command must also have been named in a FOR
UPDATE clause in the related DECLARE CURSOR command:

          EXEC SQL DECLARE AdjustQtyOnHand
         1          CURSOR FOR
         2          SELECT PartNumber,
         3                 BinNumber,
         4                 QtyOnHand,
         5                 AdjustmentQty
         6            FROM PurchDB.Inventory
         7           WHERE QtyOnHand IS NOT NULL
         8             AND AdjustmentQty IS NOT NULL
         9   FOR UPDATE OF QtyOnHand,
         1                 AdjustmentQty

          EXEC SQL OPEN AdjustQtyOnHand
        .
        .  The output host variables do not need to include
          .  indicator variables, because the SELECT command
          .  associated with the cursor eliminates any rows having
          .  null values from the active set:
        .

          EXEC SQL FETCH  AdjustQtyOnHand
         1          INTO :PartNumber,
         2               :BinNumber,
         3               :QtyOnHand,
         4               :AdjustmentQty
          .
          .
          .
          EXEC SQL UPDATE PurchDB.Inventory
         1            SET QtyOnHand     = :QtyOnHand + :AdjustmentQty,
         2                AdjustmentQty = 0
         3          WHERE CURRENT OF AdjustQtyOnHand

In this example, the order of the rows in the query result is not
important.  Therefore the SELECT command associated with cursor
AdjustQtyOnHand does not need to contain an ORDER BY clause and the
UPDATE WHERE CURRENT command can be used.

In cases where order is important and the ORDER BY clause must be used,
you can use the form of the UPDATE command described in Chapter 6 to
update values in the current row.  In this case, if more than one row
qualifies for the search condition in the UPDATE command, more rows than
just the current row will be changed:

        EXEC SQL DECLARE Inventory
       1          CURSOR FOR
       2          SELECT PartNumber,
       3                 BinNumber,
       4                 QtyOnHand,
       5                 AdjustmentQty
       6            FROM PurchDB.Inventory
       7           WHERE CountCycle = :CountCycle
       8        ORDER BY BinNumber
        .
        .
        .
        EXEC SQL FETCH  Inventory
       1          INTO :PartNumber,
       2               :BinNumber,
       3               :QtyOnHand     :QtyOnHandInd
       4               :AdjustmentQty :AdjustmentQtyInd
        .
        .   The program displays the current row.  If the
          .     QtyOnHand value is not null, the program prompts
          .     the user for an adjustment quantity.  Adjustment
          .     quantity is the difference between the quantity
          .     actually in the bin and the QtyOnHand in the row
          .     displayed. If the QtyOnHand value is null, the
          .     program prompts the user for both QtyOnHand and
          .     AdjustmentQty. Any value entered is used later to 

        .   update AdjustmentQty. The value(s) entered, as well
          .     as the current PartNumber and BinNumber, are saved
          .     until all rows have been fetched and other values
          .     accepted from the user. Then one of the following
          .     UPDATE commands is executed for each UPDATE requested
          .     by the user:
          .
        EXEC SQL UPDATE PurchDB.Inventory
       1            SET AdjustmentQty = :AdjustmentQty
       2          WHERE PartNumber = :PartNumber
       3            AND BinNumber  = :BinNumber
          .
          .
          .
        EXEC SQL UPDATE PurchDB.Inventory
       1            SET QtyOnHand =     :QtyOnHand,
       2                AdjustmentQty = :AdjustmentQty
       3          WHERE PartNumber = :PartNumber
       4            AND BinNumber  = :BinNumber

After either the UPDATE WHERE CURRENT or the UPDATE command is executed,
the current row remains the same until the FETCH command is re-executed.

The DELETE WHERE CURRENT Command 

This command can be used to delete the current row when the SELECT
command associated with the cursor does not contain one of the following:

   *   DISTINCT clause in the select list.
   *   Aggregate function in the select list.
   *   FROM clause with more than one table.
   *   ORDER BY clause.
   *   GROUP BY clause.

The DELETE WHERE CURRENT command has a very simple structure:

         DELETE FROM TableName WHERE CURRENT OF CursorName 

The DELETE WHERE CURRENT command can be used in conjunction with a cursor
declared with or without the FOR UPDATE clause:

         The program displays the current row and asks
          the user whether to update or delete it.  If the
          user wants to delete the row, the following command
          is executed:

          EXEC SQL DELETE FROM PurchDB.Inventory
         1          WHERE CURRENT OF AdjustQtyOnHand

Even though the SELECT command associated with cursor Inventory names
only some of the columns in table PurchDB.Inventory, the entire current
row is deleted.

After the DELETE WHERE CURRENT command is executed, there is no current
row.  You must re-execute the FETCH command to obtain another current
row.

As in the case of the UPDATE WHERE CURRENT command, if the SELECT command
associated with the cursor contains an ORDER BY clause or other
components listed earlier, you can use the DELETE command to delete a
row:

          EXEC SQL DELETE FROM PurchDB.Inventory
         1               WHERE PartNumber = :PartNumber
         2                 AND BinNumber  = :BinNumber

If you use the DELETE command to delete a row while using a cursor to
examine an active set, remember that more than one row will be deleted if
multiple rows satisfy the conditions specified in the WHERE clause of the
DELETE command.  In addition, the row that is current when the DELETE
command is executed remains the current row until the FETCH command is
re-executed.

The CLOSE Command 

When you no longer want to operate on the active set, you use the CLOSE
command:

          CLOSE CursorName 

The CLOSE command frees up ALLBASE/SQL internal buffers used to handle
cursor operations.  This command does not release any locks obtained
since the cursor was opened; to release locks, you must terminate the
transaction:

         The program opens a cursor and operates
          on the active set.  After the last row has
          been operated on, the cursor is closed:

          EXEC SQL CLOSE Inventory

         Additional SQL commands are executed, then
          the transaction is terminated:

          EXEC SQL COMMIT WORK

You also use the CLOSE command when you want to re-access the active set.
In this case, simply re-open the cursor after executing the CLOSE
command.  Because locks have not been released, any changes to the rows
in the active set will be those made by your program since the cursor was
first opened:

          Cursor Inventory is used to update information
          in table PurchDB.Inventory.  After the last row
          in the active set has been fetched and its information
          changed, the cursor is closed:
          EXEC SQL CLOSE Inventory

          The cursor is then re-opened to allow the program
           user to review the information and optionally make
           some last-minute adjustments:

          EXEC SQL OPEN Inventory

          After the user has reviewed all rows in the active
           set, any changes made to the active set are
           made permanent as follows:

          EXEC SQL COMMIT WORK



MPE/iX 5.0 Documentation