ループ処理

記述した条件が満たされるまで、または一定の条件が有効である限り、処理ループはグループ化されたステートメントを繰り返し実行します。

このドキュメントでは、次のトピックについて説明します。


処理ループの使用

処理ループはデータベースループと非データベースループに分類できます。

複数の処理ループを同時にアクティブにできます。ループは、アクティブな(開いている)他のループ内に埋め込んだり、ネストしたりできます。

処理ループは、対応する END-... ステートメント(END-REPEATEND-FOR など)で明示的に閉じる必要があります。

オペレーティングシステムのソートプログラムを呼び出す SORT ステートメントは、すべてのアクティブな処理ループを閉じて、新しい処理ループを開始します。

データベースループの制限

以下では次のトピックについて説明します。

有効なデータベースループの制限方法

ステートメント READFIND、または HISTOGRAM で開始した処理ループの繰り返し回数を制限するには、以下の 3 つの方法があります。

  • セッションパラメータ LT を使用する方法、

  • LIMIT ステートメントを使用する方法、

  • または、 READ/FIND/HISTOGRAM ステートメント自体のリミット表記を使用する方法。

LT セッションパラメータ

システムコマンド GLOBALS では、セッションパラメータ LT を指定できます。このパラメータを使用して、データベース処理ループで読み込むレコード件数を制限します。

例:

GLOBALS LT=100

この制限は、セッション全体のすべての READFIND、および HISTOGRAM の各ステートメントに適用されます。

LIMIT ステートメント

プログラムでは、LIMIT ステートメントを使用して、データベース処理ループで読み込むレコード件数を制限できます。

例:

LIMIT 100

別の LIMIT ステートメントまたはリミット表記によって上書きされるまで、LIMIT ステートメントはプログラムの残りの部分に適用されます。

リミット表記

READFIND、または HISTOGRAM の各ステートメント自体で、読み込むレコード件数をステートメント名の直後のカッコ内に指定できます。

例:

READ (10) VIEWXYZ BY NAME

このリミット表記は、その他の有効なあらゆる制限を上書きします。ただし、リミット表記が適用されるのは、その表記が指定されているステートメントのみです。

制限設定の優先順位

LT パラメータに設定されている制限が、LIMIT ステートメントに指定されている制限またはリミット表記よりも小さい場合、LT の制限はこれらの他の制限より優先されます。

非データベースループの制限 - REPEAT ステートメント

非データベース処理ループは、論理条件基準、または他に指定された制限条件に基づいて開始および終了します。

ここでは、非データベースループステートメントとして、REPEAT ステートメントについて説明します。

REPEAT ステートメントを使用して、繰り返し実行する 1 つ以上のステートメントを指定します。さらに、ある条件に一致するまで、または、ある条件に一致している間にのみステートメントが実行されるように、論理条件を指定できます。この目的のためには、UNTIL 節または WHILE 節を使用します。

論理条件を指定する場合、以下のようにループは制御されます。

  • UNTIL 節を使用すると、論理条件が満たされるまでREPEAT ループが続けられます。

  • WHILE 節を使用すると、論理条件が真である限りREPEAT ループが続けられます。

論理条件を指定しない場合、以下のステートメントのいずれかを使用して、REPEAT ループを抜ける必要があります。

  • ESCAPE 処理ループの実行を終了し、ループの外側の処理を継続します(下記参照)。

  • STOP Natural アプリケーション全体の実行を停止します。

  • TERMINATE Natural アプリケーションの実行を停止し、Natural セッションも終了します。

REPEAT ステートメントの例

** Example 'REPEAX01': REPEAT
************************************************************************
DEFINE DATA LOCAL
1 MYVIEW VIEW OF EMPLOYEES
  2 NAME
  2 SALARY (1:1)
*
1 #PAY1    (N8)
END-DEFINE
*
READ (5) MYVIEW BY NAME WHERE SALARY (1) = 30000 THRU 39999
  MOVE SALARY (1) TO #PAY1
  /*
  REPEAT WHILE #PAY1 LT 40000
    MULTIPLY #PAY1 BY 1.1
    DISPLAY NAME (IS=ON) SALARY (1)(IS=ON) #PAY1
  END-REPEAT
  /*
  SKIP 1
END-READ
END

プログラム REPEAX01 の出力:

Page      1                                                  14-01-14  14:15:54
                                                                                 
        NAME           ANNUAL     #PAY1                                  
                       SALARY                                            
-------------------- ---------- ---------                                
                                                                           
ADKINSON                  34500     37950                                
                                    41745                                
                                                                           
                          33500     36850                                
                                    40535                                
                                                                           
                          36000     39600                                
                                    43560                                
                                                                           
AFANASSIEV                37000     40700                                
                                                                           
ALEXANDER                 34500     37950                                
                                    41745

処理ループの終了 - ESCAPE ステートメント

ESCAPE ステートメントは、論理条件に基づいて処理ループの実行を終了するために使用します。

ESCAPE ステートメントは、IF 条件ステートメントグループのループ内、およびブレイク処理ステートメントグループ(AT END OF DATAAT END OF PAGEAT BREAK)のループ内で指定できます。また、非データベースループの基本論理条件を実装している独立操作可能なステートメントとして指定できます。

ESCAPE ステートメントには、ESCAPE ステートメントで処理ループを抜けた後にどこから処理を継続するのかを指定するオプション TOPBOTTOM が用意されています。

  • ESCAPE TOP は、処理ループの先頭から処理を継続するために使用します。

  • ESCAPE BOTTOM は、処理ループの後の最初のステートメントから処理を継続するために使用します。

同じ処理ループ内に複数の ESCAPE ステートメントを指定できます。

ESCAPE ステートメントの詳細と例については、『ステートメント』ドキュメントを参照してください。

ループ内のループ

別のデータベースステートメントによって開始されたデータベース処理ループ内にデータベースステートメントを指定できます。データベースループ開始ステートメントがこの方法で埋め込まれていると、ループの "階層" が作成され、階層ごとに、選択条件を満たす各レコードが処理されます。

複数のレベルのループを埋め込むことができます。例えば、非データベースループをデータベースループ内にネストできます。また、データベースループを非データベースループ内にネストすることもできます。データベースループおよび非データベースループは、条件付きステートメントグループ内でネストできます。

FIND ステートメントのネストの例

以下のプログラムは、2 つのループ階層を示しています。1 つの FIND ループ内に別の FIND ループがネスト、つまり埋め込まれています。

** Example 'FINDX06': FIND (two FIND statements nested)
************************************************************************
DEFINE DATA LOCAL
1 EMPLOY-VIEW VIEW OF EMPLOYEES
  2 CITY
  2 NAME
  2 PERSONNEL-ID
1 VEH-VIEW VIEW OF VEHICLES
  2 MAKE
  2 PERSONNEL-ID
END-DEFINE
*
FND1. FIND EMPLOY-VIEW WITH CITY = 'NEW YORK' OR = 'BEVERLEY HILLS'
  FIND (1) VEH-VIEW WITH PERSONNEL-ID = PERSONNEL-ID (FND1.)
    DISPLAY NOTITLE NAME CITY MAKE
  END-FIND
END-FIND
END

上記のプログラムでは、複数のファイルからデータを選択しています。外側の FIND ループでは、EMPLOYEES ファイルから、ニューヨークまたはビバリーヒルズに住んでいるすべての個人を選択しています。内側の FIND ループでは、外側のループで選択されたレコードごとに、VEHICLES ファイルからその個人の車のデータを選択しています。

プログラム FINDX06 の出力:

        NAME                 CITY                 MAKE

-------------------- -------------------- --------------------

RUBIN                NEW YORK             FORD
OLLE                 BEVERLEY HILLS       GENERAL MOTORS
WALLACE              NEW YORK             MAZDA
JONES                BEVERLEY HILLS       FORD
SPEISER              BEVERLEY HILLS       GENERAL MOTORS

プログラム内のステートメント参照

ステートメント参照表記は、以下の目的で使用します。

  • 特定の範囲のデータに対する処理を指定するために、プログラム内で前に処理したステートメントを参照するため。

  • Natural のデフォルトの参照設定を上書きするため。

  • コードをわかりやすくするため。

処理ループの開始、またはデータベースのデータ要素へのアクセスを発生させる、あらゆる Natural ステートメントを参照できます。例えば、

プログラムで複数の処理ループを使用するときは、参照表記を使用して、データベースフィールドに最初にアクセスしたステートメントを参照することにより、処理対象のデータベースフィールドを一意に指定します。

このような方法でフィールドを参照できるかどうかは、『ステートメント』ドキュメントに記載されている、対応するステートメントの説明の「オペランド定義テーブル」のステートメント参照列を参照してください。「ユーザー定義変数」の「表記 (r) を使用したデータベースフィールドの参照」も参照してください。

また、参照表記はいくつかのステートメントで指定できます。例えば、次のようになります。

参照表記がない場合、AT START OF DATAAT END OF DATA または AT BREAK ステートメントは一番外側のアクティブな READFINDHISTOGRAMSORT または READ WORK FILE ループに関連付けられます。参照表記を使用すると、別のアクティブな処理ループに関連付けることができます。

参照表記を ESCAPE BOTTOM ステートメントに指定すると、参照表記で指定した処理ループの後の最初のステートメントから処理が継続されます。

ステートメント参照表記は、ステートメント参照ラベル形式またはソースコード行番号形式で指定できます。

  • ステートメント参照ラベル
    ステートメント参照ラベルはいくつかの文字で構成され、最後には必ずピリオド(.)を使用します。ピリオドによって、そのエントリはラベルとして識別されます。

    ステートメントが含まれる行の先頭にラベルを指定することにより、参照されるステートメントをラベルでマークします。例えば、次のようになります。

    0030 ... 
    0040 READ1. READ VIEWXYZ BY NAME 
    0050 ...

    マークされたステートメントを参照するステートメントでは、ステートメントの構文図に示されている位置に、ラベルをカッコで囲んで指定します(『ステートメント』ドキュメントを参照)。例えば、次のようになります。

    AT BREAK (READ1.) OF NAME
  • ソースコード行番号
    ソースコード行番号を使用して参照する場合、行番号は、カッコで囲んだ 4 桁の数字(先行ゼロは省略不可)で指定する必要があります。例えば、次のようになります。

    AT BREAK (0040) OF NAME

    ステートメント内でラベル/行番号を使用して特定のフィールドを前のステートメントに関連付ける場合、ラベル/行番号は、フィールド名の後にカッコで囲んで指定します。例えば、次のようになります。

    DISPLAY NAME (READ1.) JOB-TITLE (READ1.) MAKE MODEL

行番号とラベルは区別なく使用できます。

ユーザー定義変数」の「表記 (r) を使用したデータベースフィールドの参照」も参照してください。

行番号を使用した参照の例

以下のプログラムでは、参照にソースコード行番号(カッコで囲んだ 4 桁の数字)を使用しています。

この例では、参照先のステートメントへのすべての参照において、デフォルトで行番号が使用されています。

0010 ** Example 'LABELX01': Labels for READ and FIND loops (line numbers)
0020 ************************************************************************
0030 DEFINE DATA LOCAL
0040 1 MYVIEW1 VIEW OF EMPLOYEES
0050   2 NAME
0060  2 FIRST-NAME
0070  2 PERSONNEL-ID
0080 1 MYVIEW2 VIEW OF VEHICLES
0090  2 PERSONNEL-ID
0100  2 MAKE
0110 END-DEFINE
0120 *
0130 LIMIT 15
0140 READ MYVIEW1 BY NAME STARTING FROM 'JONES'
0150  FIND MYVIEW2 WITH PERSONNEL-ID = PERSONNEL-ID (0140)
0160    IF NO RECORDS FOUND
0170      MOVE '***NO CAR***' TO MAKE
0180    END-NOREC
0190    DISPLAY NOTITLE NAME       (0140) (IS=ON)
0200                    FIRST-NAME (0140) (IS=ON)
0210                    MAKE       (0150)
0220  END-FIND /* (0150)
0230 END-READ   /* (0140)
0240 END

ステートメント参照ラベルを使用した参照の例

以下の例は、ステートメント参照ラベルの使用方法を示しています。

行番号の代わりにラベルが参照に使用されている点以外は、前述のプログラムと同一です。

** Example 'LABELX02': Labels for READ and FIND loops (user labels)     
************************************************************************
DEFINE DATA LOCAL                                                       
1 MYVIEW1 VIEW OF EMPLOYEES                                             
  2 NAME                                                                
  2 FIRST-NAME                                                          
  2 PERSONNEL-ID                                                        
1 MYVIEW2 VIEW OF VEHICLES                                              
  2 PERSONNEL-ID                                                        
  2 MAKE                                                                
END-DEFINE                                                              
*                                                                       
LIMIT 15                                                                
RD. READ MYVIEW1 BY NAME STARTING FROM 'JONES'                          
  FD. FIND MYVIEW2 WITH PERSONNEL-ID = PERSONNEL-ID (RD.)               
    IF NO RECORDS FOUND                                                 
      MOVE '***NO CAR***' TO MAKE                                       
    END-NOREC                                                           
    DISPLAY NOTITLE NAME       (RD.) (IS=ON)                            
                    FIRST-NAME (RD.) (IS=ON)                            
                    MAKE       (FD.)                                    
  END-FIND /* (FD.)                                                     
END-READ   /* (RD.)                                                     
END 

どちらのプログラムでも、以下の出力が生成されます。

        NAME              FIRST-NAME              MAKE
-------------------- -------------------- --------------------

JONES                VIRGINIA             CHRYSLER
                     MARSHA               CHRYSLER
                                          CHRYSLER
                     ROBERT               GENERAL MOTORS
                     LILLY                FORD
                                          MG
                     EDWARD               GENERAL MOTORS
                     LAUREL               GENERAL MOTORS
                     KEVIN                DATSUN
                     GREGORY              FORD
JOPER                MANFRED              ***NO CAR***
JOUSSELIN            DANIEL               RENAULT
JUBE                 GABRIEL              ***NO CAR***
JUNG                 ERNST                ***NO CAR***
JUNKIN               JEREMY               ***NO CAR***
KAISER               REINER               ***NO CAR***
KANT                 HEIKE                ***NO CAR***