COBOLの「USING句」は、呼び出し元からサブプログラムへデータを渡す構文として知られていますが、実はCALL文以外にも登場します。PROCEDURE DIVISION・SORT文・MERGE文でもそれぞれ異なる意味で使われており、コンテキストを正確に把握することが重要です。
この記事では、USING句が現れる3つのコンテキストを整理したうえで、OMITTEDによる省略可能な引数、COPY句を使った定義の共有、そして実務でよく直面する「引数が多すぎる問題」へのパラメータ設計パターンまで解説します。
- USING句が登場する3つのコンテキスト(CALL / PROCEDURE DIVISION / SORT・MERGE)
- PROCEDURE DIVISION USINGのルールとLINKAGE SECTIONとの対応
- SORT/MERGE文でのUSING句(複数ファイルを入力として指定する仕組み)
- OMITTEDキーワードで省略可能な引数を実装する方法
- COPY句を使って呼び元と呼び先のパラメータ定義を共有する方法
- 引数が多くなったときのパラメータ設計パターン(グループ統合・フラグ統合)
引数の渡し方(BY REFERENCE / BY CONTENT / BY VALUE)とLINKAGE SECTIONの詳細な解説は引数の使い方完全ガイドをご参照ください。CALL文自体の詳細(動的CALL・CANCEL・ネストプログラム)はCALL文完全ガイドで扱っています。本記事はUSING句の全コンテキストとパラメータ設計に焦点を当てます。
USING句が登場する3つのコンテキスト
| コンテキスト | 構文例 | 役割 |
|---|---|---|
| CALL文のUSING句 | CALL ‘SUBPGM’ USING 引数1 引数2 | 呼び元が引数をサブプログラムに渡す |
| PROCEDURE DIVISION USING句 | PROCEDURE DIVISION USING 仮引数1 仮引数2. | 呼び先(サブプログラム)が引数を受け取る |
| SORT/MERGE文のUSING句 | SORT SORT-WK … USING 入力ファイル1 入力ファイル2 | SORTの入力ファイルを複数指定する |
CALL文のUSING句とPROCEDURE DIVISION USING句はペアで機能します。SORT/MERGEのUSING句は全く異なる意味(ファイル指定)で使われます。
CALL文のUSING句
CALL文のUSING句で渡す引数には、BY REFERENCE・BY CONTENT・BY VALUEの3つのモードがあります。省略するとBY REFERENCEが適用されます。
WORKING-STORAGE SECTION.
01 WS-AMOUNT PIC 9(9)V99.
01 WS-TAX-RATE PIC V99.
01 WS-TAX-AMT PIC 9(7)V99.
01 WS-STATUS PIC X(2).
PROCEDURE DIVISION.
MOVE 50000.00 TO WS-AMOUNT
MOVE .10 TO WS-TAX-RATE
CALL 'TAXCALC' USING
BY CONTENT WS-AMOUNT *> 入力専用(呼び元を保護)
BY CONTENT WS-TAX-RATE *> 入力専用
BY REFERENCE WS-TAX-AMT *> 出力(計算結果を受け取る)
BY REFERENCE WS-STATUS *> 出力(処理結果コード)
ON EXCEPTION
DISPLAY 'モジュールが見つかりません'
MOVE 8 TO RETURN-CODE
STOP RUN
END-CALL.
BY CONTENT(入力専用)とBY REFERENCE(出力可能)を明示することで、コードを読むだけで各引数の役割がわかります。BY REFERENCEのデフォルト動作・BY VALUE(他言語連携)を含む引数渡しの詳細は引数の使い方完全ガイドを参照してください。
CALL USING句のルール
| 項目 | 説明 |
|---|---|
| 引数の個数 | 0個から規格上は上限なし(実装により制限あり) |
| 引数の型 | 変数・グループ項目・リテラル(BY CONTENTまたはBY VALUEのみ) |
| 渡す順序 | PROCEDURE DIVISION USING句の仮引数と位置で対応する |
| BY省略 | デフォルトでBY REFERENCEが適用される |
| 混在 | 引数ごとに異なるBYモードを混在させることができる |
PROCEDURE DIVISION USING句
PROCEDURE DIVISION USING句は、サブプログラム側(受け取る側)で引数に名前を付ける構文です。LINKAGE SECTIONで定義した項目名を順番に列挙します。
IDENTIFICATION DIVISION.
PROGRAM-ID. TAXCALC.
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-WORK PIC 9(10)V99.
LINKAGE SECTION. *> 引数の定義(アドレス参照)
01 LK-AMOUNT PIC 9(9)V99. *> 1番目の引数
01 LK-RATE PIC V99. *> 2番目の引数
01 LK-TAX PIC 9(7)V99. *> 3番目の引数
01 LK-STATUS PIC X(2). *> 4番目の引数
*> PROCEDURE DIVISIONに列挙する順番 = CALL USINGの順番
PROCEDURE DIVISION USING LK-AMOUNT
LK-RATE
LK-TAX
LK-STATUS.
IF LK-AMOUNT <= 0
MOVE 'NG' TO LK-STATUS
MOVE 0 TO LK-TAX
GOBACK
END-IF
COMPUTE LK-TAX = LK-AMOUNT * LK-RATE
MOVE 'OK' TO LK-STATUS
GOBACK.
PROCEDURE DIVISION USING句のルール
| ルール | 説明 |
|---|---|
| 並び順 | CALL文のUSING句と位置が対応する。名前は違っても構わない |
| LINKAGE SECTION必須 | ここに列挙する変数はLINKAGE SECTIONに定義されている必要がある |
| VALUE句禁止 | LINKAGE SECTIONの項目にVALUE句は使えない(コンパイラによりエラーまたは無視) |
| 型の一致 | 呼び元と呼び先でPIC句を合わせる(不一致はデータ破損の原因) |
| 終了はGOBACK | サブプログラムの終了はGOBACK。STOP RUNはジョブ全体を終了するので禁止 |
名前は異なっても位置で対応する
呼び元の変数名(例: WS-AMOUNT)とサブプログラムの仮引数名(例: LK-AMOUNT)は異なっていても問題ありません。COBOLの引数は位置(順番)で対応します。ただし、型(PIC句)は必ず一致させてください。型が違うとコンパイルエラーにならず、実行時にデータが壊れるバグになります。
LINKAGE SECTIONとの対応関係
*=== 呼び元(MAIN-PGM)===
WORKING-STORAGE SECTION.
01 WS-CUST-REC. *> グループ項目を渡す
05 WS-CUST-ID PIC 9(10).
05 WS-CUST-NAME PIC X(30).
05 WS-BALANCE PIC S9(9)V99.
01 WS-RESULT-CODE PIC X(2).
PROCEDURE DIVISION.
CALL 'CUST-VALIDATE' USING WS-CUST-REC *> 位置1
WS-RESULT-CODE *> 位置2
END-CALL.
*=== 呼び先(CUST-VALIDATE)===
LINKAGE SECTION.
01 LK-CUSTOMER. *> 呼び元WS-CUST-RECに対応(位置1)
05 LK-CUST-ID PIC 9(10). *> 同じ構造で定義する
05 LK-CUST-NAME PIC X(30).
05 LK-BALANCE PIC S9(9)V99.
01 LK-RESULT PIC X(2). *> 呼び元WS-RESULT-CODEに対応(位置2)
PROCEDURE DIVISION USING LK-CUSTOMER LK-RESULT.
IF LK-CUST-ID = ZEROS
MOVE 'E1' TO LK-RESULT
GOBACK
END-IF
IF LK-BALANCE < 0
MOVE 'E2' TO LK-RESULT
GOBACK
END-IF
MOVE 'OK' TO LK-RESULT
GOBACK.
SORT/MERGE文のUSING句
USING句はSORT文とMERGE文にも登場します。こちらは引数の受け渡しとは無関係で、ソートまたはマージの入力ファイルを指定するための構文です。
SORT文でのUSING句
SORT文の構造
SORT文には入力の指定方法として「USING句(ファイル指定)」と「INPUT PROCEDURE(プログラムで制御)」の2種類があります。USING句を使うと、COBOLランタイムが自動でファイルを開いてすべてのレコードを読み込んでくれます。
SORT ソートワークファイル名
ON {ASCENDING | DESCENDING} KEY キー項目名 ...
[USING 入力ファイル名1 [入力ファイル名2 ...]]
{GIVING 出力ファイル名 | OUTPUT PROCEDURE IS 手続き名}
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT TRANS-FILE ASSIGN TO 'TRANS.DAT'
ORGANIZATION IS SEQUENTIAL.
SELECT SORT-WORK ASSIGN TO SORT-WORK-AREA.
SELECT SORTED-FILE ASSIGN TO 'SORTED.DAT'
ORGANIZATION IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD TRANS-FILE.
01 TRANS-RECORD PIC X(80).
SD SORT-WORK. *> ソートワークはFDでなくSDで定義
01 SORT-RECORD.
05 SK-DATE PIC 9(8).
05 SK-AMOUNT PIC 9(9)V99.
05 FILLER PIC X(61).
FD SORTED-FILE.
01 SORTED-RECORD PIC X(80).
PROCEDURE DIVISION.
*> USINGでTRANS-FILEを指定→自動でOPEN・READ・CLOSE
*> GIVINGでSORTED-FILEへ出力→自動でOPEN・WRITE・CLOSE
SORT SORT-WORK
ON ASCENDING KEY SK-DATE
ON DESCENDING KEY SK-AMOUNT
USING TRANS-FILE
GIVING SORTED-FILE
DISPLAY 'ソート完了'
STOP RUN.
SORT USING句の最大の特徴は、ファイルのオープン・読み込み・クローズをランタイムが自動で行う点です。入力ファイルを自分でOPEN/READする必要がなく、コードが簡潔になります。
SORT文 USING句で複数ファイルを入力する
USING句には複数のファイルを指定できます。ランタイムが各ファイルのすべてのレコードを読み込んで一括ソートします。年度をまたぐデータや、システムを分けて収集したデータを一度にソートする場面で使います。
FILE-CONTROL.
SELECT JAN-FILE ASSIGN TO 'DATA-JAN.DAT' ORGANIZATION IS SEQUENTIAL.
SELECT FEB-FILE ASSIGN TO 'DATA-FEB.DAT' ORGANIZATION IS SEQUENTIAL.
SELECT MAR-FILE ASSIGN TO 'DATA-MAR.DAT' ORGANIZATION IS SEQUENTIAL.
SELECT SORT-WORK ASSIGN TO SORT-WORK-AREA.
SELECT Q1-SORTED ASSIGN TO 'Q1-SORTED.DAT' ORGANIZATION IS SEQUENTIAL.
DATA DIVISION.
FILE SECTION.
FD JAN-FILE. 01 JAN-RECORD PIC X(100).
FD FEB-FILE. 01 FEB-RECORD PIC X(100).
FD MAR-FILE. 01 MAR-RECORD PIC X(100).
SD SORT-WORK.
01 SORT-RECORD.
05 SK-CUST-CODE PIC X(8).
05 SK-TRANS-DATE PIC 9(8).
05 FILLER PIC X(84).
FD Q1-SORTED.
01 Q1-RECORD PIC X(100).
PROCEDURE DIVISION.
*> 1月・2月・3月の3ファイルをまとめてソート
SORT SORT-WORK
ON ASCENDING KEY SK-CUST-CODE
ON ASCENDING KEY SK-TRANS-DATE
USING JAN-FILE FEB-FILE MAR-FILE *> 3ファイルを一括入力
GIVING Q1-SORTED *> 1つの出力ファイルへ
DISPLAY '第1四半期データのソート完了'
STOP RUN.
| 方式 | 特徴 | 向いているケース |
|---|---|---|
| SORT USING | 複数ファイルOK・ランタイムが自動READ | 入力ファイルをそのままソートしたい場合 |
| SORT INPUT PROCEDURE | 単一制御(RELEASEでソートに送り込む) | フィルタリング・加工してからソートしたい場合 |
SORT USINGはOPEN/CLOSEが自動
SORT USING句で指定したファイルはランタイムが自動でOPEN・READします。SORT実行前に自分でOPENしてしまうと「既にオープン済み」エラーが発生します。同様にSORT後のCLOSEも不要です。
MERGE文でのUSING句
MERGE文はあらかじめソート済みの複数ファイルをひとつにまとめる命令です。MERGEのUSING句はSORT同様に入力ファイルを列挙します。ただしMERGEはSORT処理を行わないため、指定するファイルはすでにキー順にソート済みであることが前提です。
FILE-CONTROL.
SELECT REGION-EAST ASSIGN TO 'EAST-SORTED.DAT'.
SELECT REGION-WEST ASSIGN TO 'WEST-SORTED.DAT'.
SELECT REGION-NORTH ASSIGN TO 'NORTH-SORTED.DAT'.
SELECT MERGE-WORK ASSIGN TO MERGE-WORK-AREA.
SELECT NATION-FILE ASSIGN TO 'NATION.DAT'.
DATA DIVISION.
FILE SECTION.
FD REGION-EAST. 01 EAST-RECORD PIC X(80).
FD REGION-WEST. 01 WEST-RECORD PIC X(80).
FD REGION-NORTH. 01 NORTH-RECORD PIC X(80).
SD MERGE-WORK.
01 MERGE-RECORD.
05 MK-PROD-CODE PIC X(8).
05 FILLER PIC X(72).
FD NATION-FILE. 01 NATION-RECORD PIC X(80).
PROCEDURE DIVISION.
*> 東・西・北 3リージョンのソート済みファイルをマージ
MERGE MERGE-WORK
ON ASCENDING KEY MK-PROD-CODE
USING REGION-EAST *> ソート済みが前提
REGION-WEST
REGION-NORTH
GIVING NATION-FILE *> 統合後の全国ファイル
DISPLAY 'マージ完了'
STOP RUN.
OMITTEDキーワード(省略可能な引数)
CALL文のUSING句では、特定の引数を省略することを示すOMITTEDキーワードが使えます。呼び先でその引数が使われない場合に指定します。サブプログラム側ではADDRESS OF 仮引数名がNULLかどうかで省略を検出できます。
*> 引数を渡さないことを明示する
CALL 'SUBPGM' USING WS-INPUT
OMITTED *> 2番目の引数を省略
WS-OUTPUT
END-CALL.
IDENTIFICATION DIVISION.
PROGRAM-ID. LOG-WRITER.
*> 引数: 1=メッセージ(必須)2=ログレベル(省略可)3=出力コード(省略可)
DATA DIVISION.
WORKING-STORAGE SECTION.
01 WS-DEFAULT-LEVEL PIC X(1) VALUE 'I'. *> デフォルト: INFO
LINKAGE SECTION.
01 LK-MESSAGE PIC X(120). *> 必須
01 LK-LOG-LEVEL PIC X(1). *> 省略可(省略時はINFO)
01 LK-OUT-CODE PIC X(2). *> 省略可(省略時は出力なし)
PROCEDURE DIVISION USING LK-MESSAGE LK-LOG-LEVEL LK-OUT-CODE.
*> ログレベルが省略されたか確認
IF ADDRESS OF LK-LOG-LEVEL = NULL
MOVE 'I' TO WS-DEFAULT-LEVEL *> デフォルト値を使う
ELSE
MOVE LK-LOG-LEVEL TO WS-DEFAULT-LEVEL
END-IF
*> 出力コードが省略されたか確認
IF ADDRESS OF LK-OUT-CODE NOT = NULL
MOVE 'OK' TO LK-OUT-CODE *> 渡されていれば書き込む
END-IF
EVALUATE WS-DEFAULT-LEVEL
WHEN 'D' DISPLAY '[DEBUG] ' LK-MESSAGE
WHEN 'I' DISPLAY '[INFO] ' LK-MESSAGE
WHEN 'W' DISPLAY '[WARN] ' LK-MESSAGE
WHEN 'E' DISPLAY '[ERROR] ' LK-MESSAGE
END-EVALUATE
GOBACK.
WORKING-STORAGE SECTION.
01 WS-MSG PIC X(120).
01 WS-LEVEL PIC X(1).
01 WS-CODE PIC X(2).
PROCEDURE DIVISION.
*> パターン1: 全引数を渡す
MOVE 'トランザクション開始' TO WS-MSG
MOVE 'I' TO WS-LEVEL
CALL 'LOG-WRITER' USING WS-MSG WS-LEVEL WS-CODE
END-CALL
*> パターン2: ログレベルは省略(デフォルトINFOを使う)
MOVE '処理件数: 100件' TO WS-MSG
CALL 'LOG-WRITER' USING WS-MSG OMITTED WS-CODE
END-CALL
*> パターン3: 出力コードも省略
MOVE 'デバッグ情報' TO WS-MSG
MOVE 'D' TO WS-LEVEL
CALL 'LOG-WRITER' USING WS-MSG WS-LEVEL OMITTED
END-CALL
*> パターン4: オプション引数を両方省略
MOVE 'エラー発生' TO WS-MSG
CALL 'LOG-WRITER' USING WS-MSG OMITTED OMITTED
END-CALL
STOP RUN.
OMITTEDの主な用途: 追加機能を追加したいがインターフェースを変えたくない場合に、既存の呼び出し元はOMITTEDのまま、新機能を使う呼び出し元だけ実引数を渡す設計ができます。ただしADDRESS OFのチェックはランタイム環境によって動作が異なるため、プロジェクトの実行環境での動作確認を推奨します。
COPY句でパラメータ定義を共有する
呼び元と呼び先でPIC句をそれぞれ書くと、一方を修正したときに他方を更新し忘れてデータ破損が発生します。COPY句を使ってコピーブックに定義を一元管理すると、この問題を根本から防げます。
*> ファイル名: ORDERPARM.CPY
*> 注文処理サブプログラムの共通パラメータ定義
01 ORDER-PARAMS.
05 OP-ORDER-ID PIC 9(10). *> 注文番号
05 OP-CUST-CODE PIC X(8). *> 顧客コード
05 OP-ITEM-CODE PIC X(10). *> 商品コード
05 OP-QUANTITY PIC 9(5). *> 数量
05 OP-UNIT-PRICE PIC 9(7)V99. *> 単価
05 OP-DISCOUNT-RT PIC V99. *> 割引率
05 OP-TOTAL-AMT PIC 9(9)V99. *> 合計金額(出力)
05 OP-STATUS-CODE PIC X(2). *> 処理結果(出力)
05 OP-ERROR-MSG PIC X(60). *> エラーメッセージ(出力)
IDENTIFICATION DIVISION.
PROGRAM-ID. MAIN-BATCH.
DATA DIVISION.
WORKING-STORAGE SECTION.
COPY ORDERPARM. *> コピーブックをそのまま展開
PROCEDURE DIVISION.
MOVE 1001 TO OP-ORDER-ID
MOVE 'CUST-001' TO OP-CUST-CODE
MOVE 'ITEM-A001' TO OP-ITEM-CODE
MOVE 3 TO OP-QUANTITY
MOVE 1800.00 TO OP-UNIT-PRICE
MOVE .05 TO OP-DISCOUNT-RT
CALL 'ORDER-CALC' USING ORDER-PARAMS *> グループ項目ごと渡す
END-CALL
IF OP-STATUS-CODE = 'OK'
DISPLAY '合計金額: ' OP-TOTAL-AMT
ELSE
DISPLAY 'エラー: ' OP-ERROR-MSG
END-IF
STOP RUN.
IDENTIFICATION DIVISION.
PROGRAM-ID. ORDER-CALC.
DATA DIVISION.
LINKAGE SECTION.
COPY ORDERPARM. *> 呼び元と同一定義を展開
PROCEDURE DIVISION USING ORDER-PARAMS.
*> 入力チェック
IF OP-QUANTITY <= 0
MOVE 'NG' TO OP-STATUS-CODE
MOVE '数量は1以上を指定してください' TO OP-ERROR-MSG
GOBACK
END-IF
*> 合計金額の計算(割引適用)
COMPUTE OP-TOTAL-AMT =
OP-UNIT-PRICE * OP-QUANTITY * (1 - OP-DISCOUNT-RT)
MOVE 'OK' TO OP-STATUS-CODE
MOVE SPACES TO OP-ERROR-MSG
GOBACK.
COPYの恩恵: コピーブック(ORDERPARM.CPY)を1か所修正するだけで、CALLするすべてのプログラムに変更が反映されます。フィールドの追加・削除・桁数変更の漏れが原因のバグを防ぐ最も効果的な方法です。大規模バッチシステムでは共通インターフェース定義のコピーブックを作成するのが業界の標準的な実践です。
パラメータ設計パターン
実務のCOBOLプログラムでは引数が増えがちです。10個以上の引数を並べたCALL文は保守性が下がります。以下のパターンで引数の数をコントロールします。
パターン1: グループ項目にまとめる
関連する引数をひとつのグループ項目に集約します。最も基本的なパターンです。
*=== NG: 引数が10個並ぶ ===
CALL 'PROCESS' USING WS-CUST-ID WS-CUST-NAME WS-CUST-AGE
WS-ORDER-ID WS-ITEM-CODE WS-QTY WS-PRICE
WS-RESULT-CODE WS-ERROR-MSG WS-TIMESTAMP.
*=== OK: 顧客情報・注文情報・結果情報のグループに整理 ===
CALL 'PROCESS' USING WS-CUST-INFO *> 顧客グループ(ID/名前/年齢)
WS-ORDER-INFO *> 注文グループ(ID/コード/数量/価格)
WS-RESULT-INFO. *> 結果グループ(コード/メッセージ/タイムスタンプ)
パターン2: 入出力を分離する
引数を「入力グループ」と「出力グループ」の2つに分ける設計です。BY CONTENTとBY REFERENCEの明示と合わせることで、インターフェースの意図が明確になります。
WORKING-STORAGE SECTION.
01 WS-CALC-INPUT. *> 入力グループ
05 CI-AMOUNT PIC 9(9)V99.
05 CI-TAX-RATE PIC V99.
05 CI-DISCOUNT PIC V99.
05 CI-COUNTRY-CD PIC X(2).
01 WS-CALC-OUTPUT. *> 出力グループ
05 CO-TAX-AMT PIC 9(9)V99.
05 CO-NET-AMT PIC 9(9)V99.
05 CO-TOTAL-AMT PIC 9(10)V99.
05 CO-STATUS PIC X(2).
PROCEDURE DIVISION.
CALL 'PRICE-CALC'
USING BY CONTENT WS-CALC-INPUT *> 入力専用
BY REFERENCE WS-CALC-OUTPUT *> 出力先
END-CALL.
パターン3: コントロールブロックで拡張可能にする
インターフェースに将来の拡張余地を持たせるパターンです。FILLERを含む「コントロールブロック」を渡し、将来的にはFILLER部分に新フィールドを追加できます。
WORKING-STORAGE SECTION.
*> コントロールブロック(将来の拡張余地あり)
01 WS-CTRL-BLOCK.
05 CB-VERSION PIC 9(2) VALUE 01. *> インターフェースバージョン
05 CB-FLAGS.
10 CB-DEBUG-FLG PIC X VALUE 'N'.
10 CB-TRACE-FLG PIC X VALUE 'N'.
10 CB-AUDIT-FLG PIC X VALUE 'N'.
10 FILLER PIC X(7). *> 将来の拡張用
05 CB-TIMEOUT-SEC PIC 9(4) VALUE 0030.*> タイムアウト秒
05 FILLER PIC X(50). *> 将来の拡張用
01 WS-INPUT-DATA PIC X(200).
01 WS-OUTPUT-DATA PIC X(200).
01 WS-RETURN-INFO PIC X(10).
PROCEDURE DIVISION.
CALL 'FLEX-SERVICE'
USING WS-CTRL-BLOCK *> 制御情報(常に1つ)
WS-INPUT-DATA
WS-OUTPUT-DATA
WS-RETURN-INFO
END-CALL.
パターン4: RETURN-CODEを戻り値として活用する
処理結果コードだけ返せば十分な場合は引数で結果コードを渡す必要はありません。RETURN-CODEを使うことでシグネチャをシンプルに保てます。
*=== 引数がシンプルになる設計 ===
WORKING-STORAGE SECTION.
01 WS-TARGET-DATE PIC 9(8).
01 WS-RC-SAVE PIC S9(9) COMP.
PROCEDURE DIVISION.
MOVE 20260101 TO WS-TARGET-DATE
*> 入力のみ渡し、結果はRETURN-CODEで受け取る
CALL 'DATE-VALIDATE' USING BY CONTENT WS-TARGET-DATE
END-CALL
MOVE RETURN-CODE TO WS-RC-SAVE
EVALUATE WS-RC-SAVE
WHEN 0 DISPLAY '正常'
WHEN 4 DISPLAY '過去の日付(警告)'
WHEN 8 DISPLAY '無効な日付形式(エラー)'
WHEN 12 DISPLAY '範囲外の日付(重大エラー)'
END-EVALUATE.
よくある落とし穴と対策
① PROCEDURE DIVISION USINGとLINKAGE SECTIONの順番不一致
症状: LINKAGE SECTIONに定義した順番とPROCEDURE DIVISION USING句の並び順が異なっていても、コンパイルエラーにならない場合があります。しかし呼び元のCALL USINGとの対応がずれるため、実行時に別のデータが違う変数に入るバグが発生します。
対策: CALL USINGの引数リストと、PROCEDURE DIVISION USINGの仮引数リストを常に同じ順番に書きます。COPY句でパラメータ定義を共有すると順番のズレ自体が起きません。
② SORT USING指定ファイルを事前にOPENしてしまう
症状: SORT USING句で指定したファイルはランタイムが自動でOPENします。SORT実行前に自分でOPEN INPUT file-nameしてしまうと「ファイルが既にオープン状態です」という実行時エラーが発生します。
対策: SORT USING句で指定するファイルは、SORT文の直前にOPEN・CLOSEを行わないようにします。SORTの前後で同じファイルにアクセスしたい場合は、別の変数に読み込んでから処理します。
③ MERGE USINGで未ソートファイルを渡す
症状: MERGE文のUSING句で指定するファイルは昇順(またはON句で指定した順)にソート済みであることが前提です。未ソートのまま渡すと、出力結果が正しくマージされず、一見動いているように見えてデータの順序が壊れます。
対策: MERGE前に必ず各入力ファイルがソート済みであることを確認します。ソートが保証できない場合はMERGEでなくSORTを使い、複数ファイルをUSINGで一括ソートします。
④ OMITTEDを使った省略引数へのアクセス
症状: 呼び元がOMITTEDで省略した引数を、呼び先でADDRESS OFチェックなしにアクセスしようとするとセグメンテーション違反(不正なメモリアクセス)が発生します。NULLポインタへのアクセスと同じです。
対策: OMITTEDが来る可能性のある引数は、必ずIF ADDRESS OF 仮引数名 = NULLで省略されているかを確認してからアクセスします。
⑤ COPYで展開した定義を呼び元と呼び先で構造変更したとき
症状: コピーブックを修正した際に、そのコピーブックを使っているすべてのプログラムを再コンパイルしないと、古い定義のオブジェクトと新しい定義のオブジェクトが混在してデータ破損が起きます。特にフィールドの途中に新しいフィールドを追加した場合に起きやすいです。
対策: コピーブックを修正したら、そのコピーブックをCOPYしているすべてのプログラムを一括で再コンパイルします。フィールドを追加するときは末尾かFILLER部分への追加を基本とし、既存フィールドの位置が変わらないようにします。
よくある質問
CALL 'SUB' USING BY CONTENT 100 BY CONTENT 'ABC'。BY REFERENCE(デフォルト)ではリテラルを渡せません。定数を渡したい場合はWORKING-STORAGEに定数をMOVEしてからBY CONTENTで渡すか、BY CONTENTに切り替えます。まとめ
| 機能 | 概要 | 主な用途 |
|---|---|---|
| CALL文のUSING句 | 引数を呼び先に渡す。BY REFERENCE(デフォルト)/ BY CONTENT / BY VALUE | 引数渡しの主な場面 |
| PROCEDURE DIVISION USING句 | LINKAGE SECTIONの仮引数をCALL USINGの順番で列挙する | サブプログラムの引数受け取り |
| SORT文のUSING句 | 複数の入力ファイルを列挙。ランタイムが自動でOPEN/READ | 入力ファイルをそのままソートしたい場合 |
| MERGE文のUSING句 | ソート済みファイルを複数指定してマージ | 複数リージョン・期間のファイルを統合 |
| OMITTED | 省略を明示。呼び先でADDRESS OF = NULLで検出 | オプション引数の実装 |
| COPY句での共有 | コピーブックに定義を一元管理してCALL/PROCEDURE双方で展開 | 型不一致バグの根本予防 |
| グループ統合パターン | 関連引数をグループ項目にまとめてCALLを簡潔に | 引数が多すぎるインターフェースの改善 |
USING句はCALL文とPROCEDURE DIVISIONのペアで機能する引数渡しが主役ですが、SORT/MERGEでは入力ファイル指定という全く別の役割も持ちます。COPY句による定義の共有とOMITTEDによる省略可能引数を組み合わせると、保守性と柔軟性の高いインターフェース設計が実現できます。
引数の渡し方(BY REFERENCE / BY CONTENT / BY VALUE)とLINKAGE SECTIONの詳細は引数の使い方完全ガイドを、CALL文の動的/静的・CANCEL・ネストプログラムはCALL文完全ガイドを合わせてご参照ください。
