行記憶域を使用した複数行 FETCH
複数行用 FETCH ステートメントを行記憶域とともに使用するには、その前にアプリケーションで、行記憶域および関連した記述域を定義しなければなりません。
行記憶域とは、アプリケーションで定義されるホスト変数のことです。 この行記憶域には、複数行用 FETCH ステートメントの結果が入ります。 行記憶域は、複数行用 FETCH ステートメントで要求された行をすべて収容できるだけの十分なバイト数を持つ文字変数でも構いません。
行記憶域形式の複数行用 FETCH で使用される関連記述子では、返される各列の SQLTYPE と SQLLEN が入る SQLDA を定義します。 記述子に指定する情報によって、データベースから行記憶域へのデータ・マッピングが判別されます。パフォーマンスを最高にするには、記述子に指定されている属性情報が、取り出される列の属性と一致していなければなりません。
次の PL/I の例を検討してください。
*....+....1....+....2....+....3....+....4....+....5....+....6....+....7...*
EXEC SQL INCLUDE SQLCA;
EXEC SQL INCLUDE SQLDA;
...
DCL DEPTPTR PTR;
DCL 1 DEPT(20) BASED(DEPTPTR),
3 EMPNO CHAR(6),
3 LASTNAME CHAR(15) VARYING,
3 WORKDEPT CHAR(3),
3 JOB CHAR(8);
DCL I BIN(31) FIXED;
DEC J BIN(31) FIXED;
DCL ROWAREA CHAR(2000);
...
ALLOCATE SQLDA SET(SQLDAPTR);
EXEC SQL
DECLARE D11 CURSOR FOR
SELECT EMPNO, LASTNAME, WORKDEPT, JOB
FROM CORPDATA.EMPLOYEE
WHERE WORKDEPT = 'D11';
...
EXEC SQL
OPEN D11;
/* SET UP THE DESCRIPTOR FOR THE MULTIPLE-ROW FETCH */
/* 4 COLUMNS ARE BEING FETCHED */
SQLD = 4;
SQLN = 4;
SQLDABC = 366;
SQLTYPE(1) = 452; /* FIXED LENGTH CHARACTER - */
/* NOT NULLABLE */
SQLLEN(1) = 6;
SQLTYPE(2) = 456; /*VARYING LENGTH CHARACTER */
/* NOT NULLABLE */
SQLLEN(2) = 15;
SQLTYPE(3) = 452; /* FIXED LENGTH CHARACTER - */
SQLLEN(3) = 3;
SQLTYPE(4) = 452; /* FIXED LENGTH CHARACTER - */
/* NOT NULLABLE */
SQLLEN(4) = 8;
/*ISSUE THE MULTIPLE-ROW FETCH STATEMENT TO RETRIEVE*/
/*THE DATA INTO THE DEPT ROW STORAGE AREA */
/*USE A HOST VARIABLE TO CONTAIN THE COUNT OF */
/*ROWS TO BE RETURNED ON THE MULTIPLE-ROW FETCH */
J = 20; /*REQUESTS 20 ROWS ON THE FETCH */
...
EXEC SQL
WHENEVER NOT FOUND
GOTO FINISHED;
EXEC SQL
WHENEVER SQLERROR
GOTO FINISHED;
EXEC SQL
FETCH D11 FOR :J ROWS
USING DESCRIPTOR :SQLDA INTO :ROWAREA;
/* ADDRESS THE ROWS RETURNED */
DEPTPTR = ADDR(ROWAREA);
/*PROCESS EACH ROW RETURNED IN THE ROW STORAGE */
/*AREA BASED ON THE COUNT OF RECORDS RETURNED */
/*IN SQLERRD3. */
DO I = 1 TO SQLERRD(3);
IF EMPNO(I) = '000170' THEN
DO;
:
END;
END;
IF SQLERRD(5) = 100 THEN
DO;
/* PROCESS END OF FILE */
END;
FINISHED:
この例では、カーソルは、CORPDATA.EMPLOYEE 表で WORKDEPT 列が 'D11' に等しいすべての行を選択するように定義されています。 サンプル表に記載されているサンプルの EMPLOYEE 表の例では、結果表に複数行が入ることが示されています。 DECLARE CURSOR ステートメントと OPEN ステートメントには、複数行用 FETCH ステートメントとともに使用する場合の特殊な構文はありません。 同じカーソルに対して 1 つの行を返す別の FETCH ステートメントをプログラム内のほかの場所にコーディングすることができます。 複数行用 FETCH ステートメントは、結果表にすべての行を取り出すために使用されます。 FETCH の実行後、カーソルはブロック内の最終行に置かれたままになります。
行記憶域 ROWAREA は、文字配列として定義されています。結果表から取り出されたデータは、ホスト変数に入ります。この例では、ROWAREA のアドレスにポインター変数が割り当てられています。返される行内の各項目が検査され、基底付き構造 DEPT で使われます。
記述子の項目の属性 (タイプと長さ) は、取り出される列と一致しています。このケースでは、標識区域は指定されていません。
FETCH ステートメントが完了すると、ROWAREA には 'D11' と等しいすべての行 (この例では 11 行) が入ります。アプリケーションに返される SQLCA には、次の情報が入ります。
- SQLCODE には、0 が入ります。
- SQLSTATE には '00000' が入ります。
- SQLERRD3 には、返される行数を示す 11 が入ります。
- SQLERRD4 には、取り出される行の長さを示す 34 が入ります。
- SQLERRD5 には、結果表の最後の行が取り出されたことを示す +100 が入ります。
この例では、アプリケーションは、ファイルの終わりに達したことを示す標識が SQLERRD5 に入るということを利用しています。 その結果、このアプリケーションでは、さらに行の取り出しを試みるためにもう一度 SQL を呼び出す必要がありません。カーソルが挿入を即時に感知する場合は、レコードが追加されたときに SQL を呼び出す必要があります。カーソルが即時感知性を持つのは、コミットメント制御レベルが *RR 以外である場合です。