【COBOL】RETURN文完全ガイド|SORT/MERGE・GOBACK・EXIT PROGRAM・RETURNING句・EXIT SECTIONの使い分け

COBOLで「制御を戻す」命令にはRETURN・GOBACK・EXIT PROGRAM・EXITの4系統があります。中でもRETURN文はSORT/MERGEのOUTPUT PROCEDUREでソート済みレコードを1件ずつ取り出す専用命令であり、サブプログラムの終了に使うGOBACK・EXIT PROGRAMとは用途がまったく異なります。

この記事では各命令の正確な用途と使い分けを解説します。SORT/MERGEでのRETURN文の実践パターン、RETURNING句による戻り値の受け渡し、EXIT SECTION/PARAGRAPHを使った段落からの早期脱出まで網羅します。CALLの仕組みやGOBACK/STOP RUNの詳細についてはCALL文完全ガイドもあわせて参照してください。

この記事でわかること

  • RETURN文の正確な用途(SORT/MERGEのOUTPUT PROCEDUREでのレコード取り出し)
  • GOBACK・EXIT PROGRAM・STOP RUNの使い分けと選択基準
  • RETURNING句でサブプログラムから計算値を返す方法
  • EXIT SECTION・EXIT PARAGRAPHで段落・セクションから早期脱出する方法
  • SORT/MERGE + OUTPUT PROCEDURE + RETURNの実践パターン
スポンサーリンク

COBOLの「制御を戻す」命令 全体像

COBOLには「制御を移す・戻す」命令が複数ありますが、それぞれ用途が異なります。混同すると重大なバグになるため、まず全体像を把握しておきましょう。

命令 動作 使いどころ
RETURN SORT/MERGEのOUTPUT PROCEDUREで、ソート済みファイルから1レコード取り出す SORT/MERGE OUTPUT PROCEDUREの内部のみ
GOBACK サブプログラム→呼び元に制御を返す。メインプログラムならジョブ終了 サブプログラムの終了(推奨)
EXIT PROGRAM GOBACKと同じ効果。COBOL 74/85スタイルの旧構文 旧システムの保守。新規はGOBACK推奨
STOP RUN どこから実行してもジョブ全体を終了する メインプログラムの最終終了のみ
EXIT SECTION 現在のセクションの終端へジャンプし、セクションを抜ける セクション内の早期脱出
EXIT PARAGRAPH 現在の段落の終端へジャンプし、段落を抜ける 段落内の早期脱出
EXIT PERFORM インラインPERFORMループを強制終了(break相当) ループからの早期脱出(698参照)
RETURN文はサブプログラムの終了命令ではありません
「RETURN = 呼び元に戻る」はJavaやPythonでの概念です。COBOLのRETURN文はSORT/MERGE専用命令です。サブプログラムを終了して呼び元に制御を戻すにはGOBACKを使います。旧来のCOBOLコードでは誤った説明が散見されますが、標準COBOLの仕様ではRETURNとGOBACKは別物です。

RETURN文の正確な用途(SORT/MERGE OUTPUT PROCEDURE)

RETURN文はSORT文またはMERGE文にOUTPUT PROCEDURE句を指定したときに使います。ソート済みのレコードを1件ずつ取り出し、加工・出力処理を行うためのものです。

RETURN文の構文
RETURN ソートファイル名 RECORD
    [INTO 転記先データ名]
    AT END 終端処理
    [NOT AT END 通常処理]
[END-RETURN].
説明
RETURN ソートファイル名 RECORD SORT/MERGEで処理されたファイルから次の1レコードを取り出す
INTO 転記先データ名 レコードをWORKING-STORAGEの変数に転記する(省略時はFDのレコード領域に格納)
AT END 全レコードを取り出し終わったときに実行する処理(ループ終了フラグのセットなど)
NOT AT END レコードが取り出せた場合に実行する処理(省略可)
END-RETURN RETURNブロックの終端。AT END/NOT AT ENDを使う場合は必須
SORT + OUTPUT PROCEDURE + RETURNの基本パターン
FILE SECTION.
FD  WORK-SORT-FILE.
01  WS-SORT-REC.
    05 WS-DEPT-CODE    PIC X(4).
    05 WS-EMP-NO       PIC 9(6).
    05 WS-SALARY       PIC 9(8)V99.

WORKING-STORAGE SECTION.
01 WS-EOF-FLAG    PIC X(1) VALUE 'N'.
   88 WS-EOF      VALUE 'Y'.
01 WS-WORK-REC.
   05 WK-DEPT     PIC X(4).
   05 WK-EMP-NO   PIC 9(6).
   05 WK-SALARY   PIC 9(8)V99.

PROCEDURE DIVISION.
MAIN-LOGIC.
    SORT WORK-SORT-FILE
        ON ASCENDING KEY WS-DEPT-CODE
        ON ASCENDING KEY WS-EMP-NO
        USING  INPUT-FILE        *> 入力ファイルを自動READ(INPUT PROCEDURE不要)
        OUTPUT PROCEDURE PROCESS-SORTED-DATA
    STOP RUN.

*=== OUTPUT PROCEDURE: ソート後の処理 ===
PROCESS-SORTED-DATA SECTION.
    MOVE 'N' TO WS-EOF-FLAG

    *> 最初の1件を取り出す(プライミングリード)
    PERFORM GET-NEXT-RECORD

    PERFORM UNTIL WS-EOF
        *> 取り出したレコードを処理
        PERFORM PROCESS-ONE-RECORD
        PERFORM GET-NEXT-RECORD
    END-PERFORM.

GET-NEXT-RECORD.
    RETURN WORK-SORT-FILE RECORD INTO WS-WORK-REC
        AT END
            MOVE 'Y' TO WS-EOF-FLAG
        NOT AT END
            CONTINUE
    END-RETURN.

PROCESS-ONE-RECORD.
    DISPLAY WK-DEPT ' ' WK-EMP-NO ' ' WK-SALARY.
SORT文の構造:INPUT PROCEDUREとOUTPUT PROCEDUREの使い分け

  • INPUT PROCEDURE: ソート前にレコードを加工する処理。RELEASE文でソートファイルに書き込む
  • OUTPUT PROCEDURE: ソート後にレコードを処理する場所。RETURN文で1件ずつ取り出す
  • USING/GIVING: 加工不要の場合はUSING(入力ファイル直接指定)/GIVING(出力ファイル直接指定)で省略できる

RETURN文はOUTPUT PROCEDURE内でのみ有効です。通常のPROCEDURE DIVISIONで使うとコンパイルエラーになります。

GOBACKとEXIT PROGRAM

サブプログラムを終了して呼び元に制御を返すにはGOBACKまたはEXIT PROGRAMを使います。両者は動作がほぼ同じですが、細かい違いがあります。

命令 歴史 動作 使いどころ
GOBACK COBOL 74以降の標準構文 サブ→呼び元へ戻る。メインではジョブ終了 メイン・サブ両方で使える。現代COBOLの推奨
EXIT PROGRAM COBOL 74の旧スタイル サブ→呼び元へ戻る。メインでは何もしない(fallthrough) 旧システムの保守時のみ。新規記述にはGOBACK
STOP RUN COBOL 60代からある古い構文 必ずジョブ全体を終了。どのプログラムから呼んでも同じ メインの最終終了のみ。サブで使用禁止
GOBACKとEXIT PROGRAMの動作の違い
*=== EXIT PROGRAMの注意点 ===
*  EXIT PROGRAMをメインプログラムで使うと何も起きない(fallthrough)
*  GOBACK をメインで使うとジョブが終了する

IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-PGM.
PROCEDURE DIVISION.
    CALL 'SUB-PGM'
    DISPLAY '呼び元に戻りました'
    STOP RUN.    *> メインの終了はSTOP RUN

*----------------------------------
IDENTIFICATION DIVISION.
PROGRAM-ID. SUB-PGM.
PROCEDURE DIVISION.
    DISPLAY 'サブプログラム実行中'

    *> OK: GOBACKで呼び元に戻る
    GOBACK.

    *> 旧スタイル: EXIT PROGRAMでも同じ動作
    *EXIT PROGRAM.

    *> NG: サブでSTOP RUNを使うとジョブ全体が終了する
    *STOP RUN.
EXIT PROGRAMとEXITは全くの別物
EXIT PROGRAMはサブプログラムを終了して呼び元に戻る命令です。一方、EXIT(単独)は何もしない空命令で、段落の最後に書くマーカーとして使われます。EXIT SECTIONはセクション脱出、EXIT PARAGRAPHは段落脱出です。「EXIT」という単語が含まれていても意味がまったく異なるため、混同しないように注意してください。

GOBACKとEND PROGRAMの関係

COBOL 85以降ではEND PROGRAM プログラム名.でプログラムを明示的に終端できます。GOBACKとEND PROGRAMはそれぞれ独立した概念です。

END PROGRAMとGOBACKの使い方
*=== 単体プログラム(ネストなし)===
IDENTIFICATION DIVISION.
PROGRAM-ID. SINGLE-PGM.
PROCEDURE DIVISION.
    DISPLAY '処理実行'
    GOBACK.         *> 制御を返す(呼ばれていればCALL元へ、トップレベルならジョブ終了)
END PROGRAM SINGLE-PGM.    *> ソースの終端マーカー(省略可)

*=== ネストプログラム使用時 ===
IDENTIFICATION DIVISION.
PROGRAM-ID. OUTER-PGM.
PROCEDURE DIVISION.
    CALL 'INNER-PGM'
    STOP RUN.    *> 親プログラムの終了

IDENTIFICATION DIVISION.
PROGRAM-ID. INNER-PGM.
PROCEDURE DIVISION.
    DISPLAY '内部プログラム'
    GOBACK.              *> 親プログラムに制御を返す
END PROGRAM INNER-PGM.  *> ネストプログラムではEND PROGRAMが必須

END PROGRAM OUTER-PGM.
パターン 挙動
GOBACKあり + END PROGRAMあり 通常の書き方。GOBACKで制御を返し、END PROGRAMでソース終端を明示。ネストプログラムでは必須
GOBACKあり + END PROGRAMなし 単独プログラムなら問題なし。ネストプログラムを使う場合はEND PROGRAMが必須
GOBACKなし + END PROGRAMあり PROCEDURE DIVISIONの末尾に達したとき、暗黙的にGOBACKと同じ動作になる(フォールスルー終了)。明示的なGOBACKを書く方が推奨
STOP RUN + END PROGRAMあり STOP RUNがGOBACKより先に実行されるためEND PROGRAMに意味はなくなるが、ソース構造上の終端マーカーとして書いても問題なし

RETURNING句でサブプログラムから値を返す

COBOL 2002以降の標準規格では、CALL文にRETURNING句を使ってサブプログラムから値を受け取れます。RETURN-CODEを介したコード伝播とは異なり、任意のデータ型で値を返せます。

CALL…RETURNINGの構文と使い方
*=== 呼び元 ===
WORKING-STORAGE SECTION.
01 WS-INPUT-VAL   PIC 9(7)V99.
01 WS-TAX-RESULT  PIC 9(7)V99.

PROCEDURE DIVISION.
    MOVE 10000.00 TO WS-INPUT-VAL
    CALL 'CALC-TAX'
        USING BY CONTENT WS-INPUT-VAL
        RETURNING WS-TAX-RESULT    *> サブの戻り値をWS-TAX-RESULTに受け取る
    END-CALL
    DISPLAY '税額: ' WS-TAX-RESULT
    STOP RUN.

*=== サブプログラム ===
IDENTIFICATION DIVISION.
PROGRAM-ID. CALC-TAX.

DATA DIVISION.
LINKAGE SECTION.
01 LK-AMOUNT    PIC 9(7)V99.
01 LK-TAX-OUT   PIC 9(7)V99.    *> RETURNING で返す変数

PROCEDURE DIVISION USING LK-AMOUNT
                   RETURNING LK-TAX-OUT.
    COMPUTE LK-TAX-OUT ROUNDED = LK-AMOUNT * 0.10
    GOBACK.
RETURNING句の注意点

  • COBOL 2002以降の標準機能。IBM z/OS COBOLでは対応状況がバージョン依存のため事前確認が必要
  • GnuCOBOL(旧OpenCOBOL)では使用可能
  • RETURNING句に指定する変数はLINKAGE SECTIONの最後の項目に対応する
  • 互換性が心配な環境ではUSING BY REFERENCE + RETURN-CODEの組み合わせを使う方が確実

PERFORM…RETURNINGで段落から値を返す

COBOL 2002以降では、PERFORM文にもRETURNINGを使って段落・セクションから値を返せます(関数スタイルの呼び出し)。ただしこれも実装依存度が高い機能です。

PERFORM…RETURNINGの構文(COBOL 2002+)
WORKING-STORAGE SECTION.
01 WS-RADIUS    PIC 9(5)V99 VALUE 5.00.
01 WS-AREA      PIC 9(9)V99.

PROCEDURE DIVISION.
    PERFORM CALC-CIRCLE-AREA
        USING BY CONTENT WS-RADIUS
        RETURNING WS-AREA
    DISPLAY '面積: ' WS-AREA
    STOP RUN.

CALC-CIRCLE-AREA SECTION.
    *> このスタイルはCOBOL 2002+かつ実装依存
    *> 汎用性が必要な場合はCALLによる外部サブプログラムを推奨
    COMPUTE WS-AREA = 3.14159 * WS-RADIUS * WS-RADIUS
    EXIT SECTION.
PERFORM…RETURNINGは実環境での使用に注意
PERFORM…RETURNING構文はCOBOL 2002以降の標準に含まれますが、IBM z/OS COBOLやMicro Focus COBOLなど主要な商用コンパイラではサポート状況がバージョンによって異なります。実際の業務システムで安全に値を返すには、サブプログラム(外部CALL)+ USING BY REFERENCEで結果用変数を直接書き換えるパターンか、CALL…RETURNINGを使うのが確実です。

EXIT SECTIONとEXIT PARAGRAPHによる早期脱出

PERFORMのループ内ではEXIT PERFORMを使いますが、セクションや段落の中での条件分岐による早期脱出にはEXIT SECTION/EXIT PARAGRAPHを使います。

EXIT SECTIONで早期脱出(ガード節パターン)
PROCEDURE DIVISION.
    PERFORM VALIDATE-INPUT-SECTION
    IF RETURN-CODE = 8
        DISPLAY '入力エラーで中断'
        STOP RUN
    END-IF
    PERFORM PROCESS-DATA-SECTION
    STOP RUN.

*=== セクション内でEXIT SECTIONを使ったガード節 ===
VALIDATE-INPUT-SECTION SECTION.
    *--- バリデーション開始 ---
    IF WS-INPUT-DATA = SPACES
        MOVE 8 TO RETURN-CODE
        EXIT SECTION    *> セクションの末尾にジャンプして抜ける
    END-IF

    IF WS-AMOUNT NOT NUMERIC
        MOVE 8 TO RETURN-CODE
        EXIT SECTION
    END-IF

    IF WS-DATE(1:4) < '2000'
        MOVE 8 TO RETURN-CODE
        EXIT SECTION
    END-IF

    *--- 全バリデーション通過 ---
    MOVE 0 TO RETURN-CODE.
VALIDATE-END.
    EXIT.
EXIT PARAGRAPHで段落から早期脱出
PROCEDURE DIVISION.
    PERFORM CHECK-RECORD
    ...

CHECK-RECORD.
    *> 削除フラグが立っていたらスキップ
    IF WS-DEL-FLAG = 'D'
        EXIT PARAGRAPH    *> この段落の残り処理をスキップ
    END-IF

    *> 金額が0以下もスキップ
    IF WS-AMOUNT <= 0
        EXIT PARAGRAPH
    END-IF

    *> 正常レコードの処理
    ADD WS-AMOUNT TO WS-TOTAL
    ADD 1 TO WS-COUNT.
命令 動作 使いどころ
EXIT SECTION セクション(SECTION)の末尾にジャンプする PERFORMで呼んだSECTION内での早期脱出。バリデーションのガード節に便利
EXIT PARAGRAPH 段落(パラグラフ)の末尾にジャンプする PERFORMで呼んだ段落内での早期脱出。レコードのスキップ処理などに便利
EXIT 何もしない空命令(ダミー文) 段落の終端マーカーとして書く。PERFORMの対象段落として正しく認識させるための構文上の工夫
EXIT PERFORM インラインPERFORMのループを強制終了(break相当) ループ内の早期終了。PERFORM文の詳細は698参照
EXIT PERFORM CYCLE インラインPERFORMの次の反復へスキップ(continue相当) ループ内の処理スキップ。PERFORM文の詳細は698参照

実践パターン

売上データのソートと集計(SORT + RETURN)

部門コードと社員番号でソートした売上レコードを、OUTPUT PROCEDUREの中でRETURNしながら部門別小計を集計するパターンです。

売上データの部門別集計(SORT/RETURN実践)
FILE SECTION.
FD  SORT-SALES-FILE.
01  SS-REC.
    05 SS-DEPT    PIC X(4).
    05 SS-EMP     PIC 9(6).
    05 SS-AMOUNT  PIC 9(8)V99.

WORKING-STORAGE SECTION.
01 WS-EOF         PIC X(1) VALUE 'N'.
   88 EOF-REACHED VALUE 'Y'.
01 WS-WORK-REC.
   05 WK-DEPT    PIC X(4).
   05 WK-EMP     PIC 9(6).
   05 WK-AMOUNT  PIC 9(8)V99.
01 WS-PREV-DEPT  PIC X(4) VALUE SPACES.
01 WS-SUBTOTAL   PIC 9(10)V99 VALUE 0.
01 WS-GRAND-TOT  PIC 9(12)V99 VALUE 0.

PROCEDURE DIVISION.
MAIN-LOGIC.
    OPEN INPUT  SALES-FILE
    SORT SORT-SALES-FILE
        ON ASCENDING KEY SS-DEPT
        ON ASCENDING KEY SS-EMP
        INPUT PROCEDURE  LOAD-SORT-DATA
        OUTPUT PROCEDURE CALC-SUBTOTAL
    CLOSE SALES-FILE
    DISPLAY '総合計: ' WS-GRAND-TOT
    STOP RUN.

*=== INPUT PROCEDURE: RELEASE でソートファイルに送る ===
LOAD-SORT-DATA SECTION.
    READ SALES-FILE INTO WS-WORK-REC
        AT END MOVE 'Y' TO WS-EOF
    END-READ
    PERFORM UNTIL EOF-REACHED
        RELEASE SS-REC FROM WS-WORK-REC
        READ SALES-FILE INTO WS-WORK-REC
            AT END MOVE 'Y' TO WS-EOF
        END-READ
    END-PERFORM.
LOAD-END.  EXIT.

*=== OUTPUT PROCEDURE: RETURN でソート済みレコードを取り出す ===
CALC-SUBTOTAL SECTION.
    MOVE 'N' TO WS-EOF

    RETURN SORT-SALES-FILE RECORD INTO WS-WORK-REC
        AT END MOVE 'Y' TO WS-EOF
    END-RETURN

    PERFORM UNTIL EOF-REACHED
        IF WS-PREV-DEPT NOT = WK-DEPT
            *> 部門切り替わり→前の部門の小計を出力
            IF WS-PREV-DEPT NOT = SPACES
                DISPLAY '部門 ' WS-PREV-DEPT ' 小計: ' WS-SUBTOTAL
            END-IF
            MOVE WK-DEPT TO WS-PREV-DEPT
            MOVE 0 TO WS-SUBTOTAL
        END-IF

        ADD WK-AMOUNT TO WS-SUBTOTAL WS-GRAND-TOT

        RETURN SORT-SALES-FILE RECORD INTO WS-WORK-REC
            AT END MOVE 'Y' TO WS-EOF
        END-RETURN
    END-PERFORM

    *> 最終部門の小計を出力
    IF WS-PREV-DEPT NOT = SPACES
        DISPLAY '部門 ' WS-PREV-DEPT ' 小計: ' WS-SUBTOTAL
    END-IF.
CALC-END.  EXIT.

RETURNINGで計算結果を返す(消費税計算モジュール)

RETURNING句を使って消費税計算モジュールから税額と税込み価格を返す実装例です。複数の値を返す場合はUSING + BY REFERENCEが確実ですが、単一値の返却パターンとして参考にしてください。

消費税計算モジュール(CALL + USING BY REFERENCE)
*=== 呼び元: メインプログラム ===
WORKING-STORAGE SECTION.
01 WS-PRICE-INFO.
   05 WS-BASE-PRICE    PIC 9(7)V99.   *> 税抜き価格
   05 WS-TAX-RATE      PIC V99.       *> 税率(0.10 = 10%)
   05 WS-TAX-AMOUNT    PIC 9(7)V99.   *> 計算後: 税額
   05 WS-TOTAL-PRICE   PIC 9(7)V99.   *> 計算後: 税込み価格

PROCEDURE DIVISION.
    MOVE 50000.00 TO WS-BASE-PRICE
    MOVE 0.10     TO WS-TAX-RATE

    *> BY REFERENCEでグループ項目を渡すと税額・税込みが書き戻される
    CALL 'TAX-CALC'
        USING BY REFERENCE WS-PRICE-INFO
    END-CALL

    DISPLAY '税抜: ' WS-BASE-PRICE
    DISPLAY '税額: ' WS-TAX-AMOUNT
    DISPLAY '税込: ' WS-TOTAL-PRICE
    STOP RUN.

*=== サブプログラム: TAX-CALC ===
IDENTIFICATION DIVISION.
PROGRAM-ID. TAX-CALC.

DATA DIVISION.
LINKAGE SECTION.
01 LK-PRICE-INFO.
   05 LK-BASE-PRICE    PIC 9(7)V99.
   05 LK-TAX-RATE      PIC V99.
   05 LK-TAX-AMOUNT    PIC 9(7)V99.
   05 LK-TOTAL-PRICE   PIC 9(7)V99.

PROCEDURE DIVISION USING LK-PRICE-INFO.
    COMPUTE LK-TAX-AMOUNT ROUNDED =
        LK-BASE-PRICE * LK-TAX-RATE
    COMPUTE LK-TOTAL-PRICE =
        LK-BASE-PRICE + LK-TAX-AMOUNT
    MOVE 0 TO RETURN-CODE
    GOBACK.

EXIT SECTIONを使った多段バリデーション

入力ファイルのレコードに対して複数のバリデーションを行い、いずれかに違反したら即座にEXIT SECTIONで抜けるパターンです。ネストが深くなることなく、条件が明確になります。

EXIT SECTIONを使った多段バリデーション
WORKING-STORAGE SECTION.
01 WS-INPUT-REC.
   05 WS-CUST-ID    PIC 9(8).
   05 WS-AMOUNT     PIC S9(9)V99 COMP-3.
   05 WS-TRX-DATE   PIC X(8).
   05 WS-TRX-TYPE   PIC X(2).
01 WS-VALID-FLAG    PIC X(1) VALUE 'Y'.
   88 INPUT-VALID   VALUE 'Y'.
01 WS-ERR-MSG       PIC X(80).

PROCEDURE DIVISION.
    READ INPUT-FILE INTO WS-INPUT-REC
        AT END MOVE 'N' TO WS-EOF-FLAG
    END-READ

    PERFORM UNTIL WS-EOF
        MOVE 'Y' TO WS-VALID-FLAG
        MOVE SPACES TO WS-ERR-MSG
        PERFORM VALIDATE-RECORD-SECTION

        IF INPUT-VALID
            PERFORM PROCESS-VALID-RECORD
        ELSE
            DISPLAY 'NG: ' WS-CUST-ID ' ' WS-ERR-MSG
            ADD 1 TO WS-ERR-COUNT
        END-IF

        READ INPUT-FILE INTO WS-INPUT-REC
            AT END MOVE 'N' TO WS-EOF-FLAG
        END-READ
    END-PERFORM
    STOP RUN.

VALIDATE-RECORD-SECTION SECTION.
    *--- ① 顧客IDの数値チェック ---
    IF WS-CUST-ID NOT NUMERIC
        MOVE 'N' TO WS-VALID-FLAG
        MOVE '顧客IDが数値ではありません' TO WS-ERR-MSG
        EXIT SECTION    *> 以降のチェックをスキップ
    END-IF

    *--- ② 金額の符号チェック ---
    IF WS-AMOUNT < 0
        MOVE 'N' TO WS-VALID-FLAG
        MOVE '金額がマイナスです' TO WS-ERR-MSG
        EXIT SECTION
    END-IF

    *--- ③ 日付形式チェック ---
    IF WS-TRX-DATE(5:2) > '12'
        MOVE 'N' TO WS-VALID-FLAG
        MOVE '日付の月部分が不正です' TO WS-ERR-MSG
        EXIT SECTION
    END-IF

    *--- ④ 取引種別コードチェック ---
    IF WS-TRX-TYPE NOT = '01' AND
       WS-TRX-TYPE NOT = '02' AND
       WS-TRX-TYPE NOT = '03'
        MOVE 'N' TO WS-VALID-FLAG
        MOVE '不正な取引種別コードです' TO WS-ERR-MSG
        EXIT SECTION
    END-IF
    *--- 全チェック通過 ---
VALIDATE-END.
    EXIT.

複数ファイルのマージと出力(MERGE + RETURN)

MERGE文でも同様にRETURNを使って処理結果を取り出せます。複数の既にソート済みのファイルを結合して出力するパターンです。

MERGE + OUTPUT PROCEDURE + RETURN
FILE SECTION.
FD  MERGE-WORK-FILE.
01  MW-REC.
    05 MW-DATE     PIC X(8).
    05 MW-LOG-LVL  PIC X(5).
    05 MW-MESSAGE  PIC X(100).

WORKING-STORAGE SECTION.
01 WS-MERGE-EOF  PIC X VALUE 'N'.
   88 MERGE-EOF  VALUE 'Y'.
01 WS-MERGE-REC.
   05 WM-DATE    PIC X(8).
   05 WM-LOG-LVL PIC X(5).
   05 WM-MSG     PIC X(100).

PROCEDURE DIVISION.
    OPEN OUTPUT MERGED-LOG-FILE

    *> 2つのソート済みログファイルを日付順にマージ
    MERGE MERGE-WORK-FILE
        ON ASCENDING KEY MW-DATE
        ON ASCENDING KEY MW-LOG-LVL
        USING  LOG-FILE-A LOG-FILE-B   *> 複数ファイル指定可能
        OUTPUT PROCEDURE WRITE-MERGED-LOG

    CLOSE MERGED-LOG-FILE
    STOP RUN.

WRITE-MERGED-LOG SECTION.
    MOVE 'N' TO WS-MERGE-EOF

    RETURN MERGE-WORK-FILE RECORD INTO WS-MERGE-REC
        AT END MOVE 'Y' TO WS-MERGE-EOF
    END-RETURN

    PERFORM UNTIL MERGE-EOF
        *> ERRORレベルのログだけ出力ファイルに書き出す
        IF WM-LOG-LVL = 'ERROR'
            WRITE MERGED-LOG-REC FROM WS-MERGE-REC
        END-IF

        RETURN MERGE-WORK-FILE RECORD INTO WS-MERGE-REC
            AT END MOVE 'Y' TO WS-MERGE-EOF
        END-RETURN
    END-PERFORM.
MERGE-END.
    EXIT.

よくある落とし穴と対策

落とし穴 症状 対策
RETURN文をサブプログラムの終了に使う 構文エラーまたは意図しない動作になる。RETURN文はSORT/MERGE専用であり、サブプログラムの終了には使えない サブプログラムの終了はGOBACKを使う
EXIT PROGRAMをメインで使い、ジョブが終了しない EXIT PROGRAMはメインプログラムで実行すると何もしない。STATEMENTが続く場合そのままフォールスルーする メインプログラムの終了はSTOP RUNを使う。GOBACKもメインではジョブ終了なので使える
EXIT SECTIONとEXIT PERFORMを混同する EXIT SECTIONはPERFORMで呼んだSECTIONから抜けるが、EXIT PERFORMはインラインPERFORMループを終了させる。用途が異なる 脱出したい範囲に応じて命令を使い分ける
RETURN文のAT END処理でEOFフラグをセットし忘れる AT ENDが実行されてもRETURNループが終了しない。無限ループになる AT ENDの中で必ずEOFフラグをセットし、PERFORMの終了条件として使う
RETURNING句の互換性を確認せずに使う COBOL 2002+の機能のため、旧コンパイラではコンパイルエラーになる。特にIBM z/OS COBOLはバージョン依存 使用前にコンパイラのバージョンと対応状況を確認する。不安な場合はUSING BY REFERENCEで代替する

よくある質問

QCOBOLのRETURN文はJavaのreturn文と同じですか?
A異なります。JavaのreturnはCOBOLのGOBACKに相当します。COBOLのRETURN文はSORT/MERGEのOUTPUT PROCEDUREでソート済みレコードを1件取り出すための専用命令です。COBOLでメソッドの呼び出し元に制御を返すにはGOBACK(サブプログラム終了)またはEXIT PROGRAM(旧スタイル)を使います。
QSORT文のINPUT PROCEDUREでもRETURNを使いますか?
Aいいえ。INPUT PROCEDUREではRELEASE文を使います。RELEASE文はソート前のレコードをソートファイルに送る命令です。RETURN文はOUTPUT PROCEDUREでソート後のレコードを取り出すときにだけ使います。覚え方:ソートファイルへの「送り込み」はRELEASE、「取り出し」はRETURNです。
QEXIT PROGRAMとGOBACKはどちらを使うべきですか?
A新規コーディングではGOBACKを使いましょう。どちらもサブプログラムを終了して呼び元に戻る効果は同じですが、GOBACKの方がメインプログラムでも意図どおりにジョブ終了するため動作が一貫しています。EXIT PROGRAMはCOBOL 74時代の旧スタイルで、旧システムの保守時に出会うことがある程度です。
QSORT文でOUTPUT PROCEDUREを使わずGIVINGで出力ファイルに書き出す場合、RETURNは必要ですか?
A不要です。GIVINGはソート済みのレコードを指定した出力ファイルに自動的に書き出します。RETURN文はOUTPUT PROCEDUREを使う場合にのみ必要です。レコードを加工せずそのまま出力ファイルに書き出すだけなら、USINGとGIVINGの組み合わせで記述が最もシンプルになります。
QEXIT SECTIONの後に「VALIDATE-END. EXIT.」のような段落を書く理由は何ですか?
AEXIT SECTIONは「セクションの末尾へジャンプする」命令ですが、コンパイラがセクションの終端を認識するために、最後に空の段落(EXIT.のみを含む段落)を置くパターンが慣習的に使われます。この「終端マーカー段落」はGOTO文や構造化PERFORMと組み合わせて使うときに終端位置を明確にする効果があります。単純な構成なら省略可能なケースもありますが、可読性と保守性のために書くことを推奨します。

まとめ

COBOLで「制御を戻す」命令は用途ごとに使い分けが重要です。

命令/構文 用途・ポイント
RETURN SORT/MERGE OUTPUT PROCEDUREでの1件取り出し。サブ終了には使えない
GOBACK サブプログラムの終了・呼び元への制御返却。新規記述の推奨
EXIT PROGRAM GOBACKと同等の旧スタイル。メインでは何もしない点に注意
STOP RUN ジョブ全体の終了。メインの最終行のみ。サブ使用禁止
EXIT SECTION PERFORMで呼んだセクションから早期脱出。ガード節パターンに有効
EXIT PARAGRAPH PERFORMで呼んだ段落から早期脱出。スキップ処理に有効
RETURNING句 CALL文でサブからの戻り値を受け取る(COBOL 2002+。環境依存に注意)

特にRETURN文はSORT/MERGE専用という点を押さえておきましょう。サブプログラムの終了にはGOBACK、複雑なCALL連鎖の設計についてはCALL文完全ガイドをあわせて参照してください。

SORT/MERGEのINPUT PROCEDUREで使うRELEASE文と組み合わせることで、ソート前後の加工処理を柔軟に実装できます。OUTPUT PROCEDUREを使ったRETURNパターンは、部門別小計・フィルタリング出力・マージ処理など実業務で頻繁に登場します。