e-learning、オラクル研修、LMS(学習管理システム)のiStudy

e-learning、オラクル研修、LMS(学習管理システム)のiStudy

第11回 「カーソルFORループ文で、ヘッダー・ディテールも簡単」

2012.02.27

普通、ヘッダー・ディテール形式で画面にデータを表示するプログラムは複雑な記述が必要です。
例えば、まず1行、部門のデータがあり、その下に複数行にわたりその部門の社員の情報を表示する。そして、また次の部門のデータを1行表示して同じことを繰り返す、といった処理です。
そのような表示は単純なSELECT文では難しいし、プログラミングするとしても、ヘッダー(部門)のループ処理の中にディテール(社員)のループ処理を記述しなければなりません。
つまり、どうしても2重のループ構造になるので、プログラミングが複雑です。

しかし、カーソルFORループ文を使えば、2重のループ構造でも、非常に簡単にプログラミングできます。
以下の例をご覧ください。わずか8行で2重ループ処理をしています。

SQL>SET serveroutput ON

  1  BEGIN
  2     FOR REC1 IN (SELECT * FROM DEPT) LOOP
  3          DBMS_OUTPUT.PUT_LINE(CHR(10) || '### 部門名 : ' || REC1.DNAME || ' ####');
  4          FOR REC2 IN (SELECT * FROM EMP WHERE DEPTNO = REC1.DEPTNO) LOOP
  5             DBMS_OUTPUT.PUT_LINE(REC2.ENAME || 'の入社日は、' ||
REC2.HIREDATE || ' です');
  6          END LOOP;
  7     END LOOP;
  8* END;
SQL> /

### 部門名 : ACCOUNTING ####
CLARKの入社日は、81-06-09 です
KINGの入社日は、81-11-17 です
MILLERの入社日は、82-01-23 です

### 部門名 : RESEARCH ####
SMITHの入社日は、80-12-17 です
JONESの入社日は、81-04-02 です
SCOTTの入社日は、87-04-19 です
ADAMSの入社日は、87-05-23 です
FORDの入社日は、81-12-03 です

### 部門名 : SALES ####
ALLENの入社日は、81-02-20 です
WARDの入社日は、81-02-22 です
MARTINの入社日は、81-09-28 です
BLAKEの入社日は、81-05-01 です
TURNERの入社日は、81-09-08 です
JAMESの入社日は、81-12-03 です

### 部門名 : OPERATIONS ####

PL/SQLプロシージャが正常に完了しました。

SQL>

いかがですか?わずか8行で、ヘッダー・ディテール形式で画面に表示していますね。

ここでポイントは、外側のループ(2-7行目)は部門表(DEPT)のカーソルFORループ文ですが、その1行は、REC1変数に格納されます。内側のループ(4-6行目)は社員表(EMP)のカーソルFORループ文であり、その1行はREC2変数に格納されます。そして非常に大事なことは内側のカーソルFORループ文のSELECT文のWHERE句の条件が外側の行(REC1)の値を引き継いでいるということです。(4行目 WHERE DEPTNO = REC1.DEPTNO)

これにより、内側のループでは、外側のループの部門に所属する社員の問合せが可能になります。
このようにカーソルFORループ文を使えば、2重ループ処理でも大変少ないステップ数で簡単に記述できるのです。

なお、3行目に CHR(10)という記述がありますが、これは改行を表します。部門替わりの時に、空白行を入れたかったので記述しました。SQL*PlusでDBMS_OUTPUTなどで空白行を設けたいとき、便利です。参考にしてください。(SQL*Plusでは、DBMS_OUTPUT.PUT_LINEで空白文字を出力しても空白行にならないので)

それでは、今回はここまでです。次回、ご期待ください。

先頭へ戻る