COBOLの「START文」とは?使い方や注意点を解説!

2025年4月11日金曜日

COBOL

「COBOLのSTART文」、ファイルの途中から読み込みを開始したい時に使う、あの命令のことですね!

COBOLでファイルを扱うとき、最初から最後まで順番に読むだけでなく、「特定の条件に合うレコードから読み始めたい!」なんて思うこと、ありませんか? 例えば、社員番号が '0100' 以上の人だけを処理したい、とか。

そんな時に活躍するのが、この「START文」なんです。

この記事では、COBOLのSTART文について、基本的な役割から書き方、サンプルファイルの準備、実際の使い方、そして「あれ?」となりがちな注意点まで、しっかり解説していきます。

この記事で学べること

  • START文がどんな役割を持つ命令なのか
  • START文の基本的な書き方のルール
  • START文を試すためのサンプルファイルの作り方
  • START文を使ったサンプルプログラムとその動き
  • START文を使うときに気をつけるポイント (READ文との違いも)

COBOLの「START文」とは?ファイル読み込みの開始位置を決める命令

まず、COBOLのSTART文がどんなお仕事をする命令なのか、イメージを掴みましょう。

START文は、一言でいうと、索引編成ファイルや相対編成ファイルの中の、特定のレコードを基準にして、次に読み込むべきレコードの位置を決める(位置付けする)ための命令です。

重要なのは、START文自体はレコードを読み込まない、という点です。あくまで「ここから読み始めるぞ!」というスタート地点を決めるだけなんですね。

実際の読み込みは、その後に続く `READ` 文(特に `READ NEXT` 文)が行います。

例えば、大量のデータが入ったファイルから、ある条件(キーが特定の値以上、など)に合う最初のレコードを見つけ出して、そこから順番に処理を進めたい…そんな時に、START文がファイルの「しおり」のように機能してくれるわけです。

「START文」の基本的な書き方

START文の基本的な形を見てみましょう。いくつかのオプションがありますが、まずは骨格となる部分です。

START ファイル名
      KEY IS 関係演算子 データ項目名
      INVALID KEY
          命令文...
      NOT INVALID KEY
          命令文...
END-START. *> 省略可能な場合もある

一つずつ見ていきましょう。

ファイル名の指定

`START` の後に、位置付けを行いたいファイルの名前を指定します。

`ENVIRONMENT DIVISION` の `SELECT`句で指定したファイル名を書く、というルールも同じです。例えば `SELECT 社員ファイル ...` と定義していたら、`START 社員ファイル ...` のように記述します。

KEY IS 句 (比較条件の指定)

ここがSTART文のキモとなる部分です!

`KEY IS` 句では、どのキー項目を使って、どのように比較して、読み込み開始位置を決めるのかを指定します。

KEY IS 関係演算子 データ項目名
  • 関係演算子: どのように比較するかを指定します。よく使うのは以下のものです。
    • `EQUAL TO` または `=` : キーが指定した値と等しい最初のレコード
    • `GREATER THAN` または `>` : キーが指定した値より大きい最初のレコード
    • `NOT LESS THAN` または `NOT <` : キーが指定した値以上 (`GREATER THAN OR EQUAL TO` / `>=` と同じ意味) の最初のレコード
    • 他にも `LESS THAN (<)`, `NOT GREATER THAN (NOT >)` などがあります。
  • データ項目名: 比較の基準となる値が入っているデータ項目(通常は `WORKING-STORAGE SECTION` などで定義した変数)を指定します。このデータ項目名は、`SELECT`句で `RECORD KEY IS` に指定したキー項目と同じ PICTURE句(型と桁数)である必要があります。

例えば、「社員番号(RECORD KEY)が '0002' 以上の最初のレコード」に位置付けたい場合は、`WORKING-STORAGE` に `WS-START-KEY PIC X(4) VALUE '0002'.` のような変数を用意しておき、`KEY IS NOT LESS THAN WS-START-KEY` のように書きます。

INVALID KEY 句

`INVALID KEY` 句は、START文による位置付けが失敗した場合に実行される処理を書く部分です。

例えば、`KEY IS EQUAL TO` で指定した値を持つレコードがファイル内に一つも存在しなかった場合や、`KEY IS GREATER THAN` で指定した値より大きいレコードが一つもなかった場合などに、この `INVALID KEY` の部分が実行されます。

「指定された条件に合う開始位置が見つかりませんでしたよ」というエラー処理をここで行うのが一般的です。

逆に、`NOT INVALID KEY` 句は、位置付けが成功した場合に実行される処理を書く部分です。省略されることも多いですが、「正常に位置付けできました」という処理が必要な場合に記述します。

`END-START` は、これらの処理の範囲を明確にするための閉じタグのようなものです(COBOLのバージョンや書き方によっては省略可能な場合もあります)。

COBOLの「START文」を試してみよう

サンプルで使うファイルを用意しよう

START文を試すためにも、まずはデータが入ったファイルが必要です。
ここでは、`SHAIN.DAT` (社員情報ファイル)を作成します。

使うのは、以下の構造の索引編成ファイルです。

  • ファイル名: SHAIN.DAT
  • ファイルの種類: 索引編成ファイル (ORGANIZATION IS INDEXED)
  • レコードの構成:
    • 社員番号 (SHAIN-BANGOU): 4桁の文字 (PIC X(4)) ← これがキー
    • 氏名 (SHAIN-NAME): 10桁の文字 (PIC X(10))
    • 年齢 (SHAIN-AGE): 2桁の数字 (PIC 9(2))

作成後のファイルの中身はこんな感じです。

0001TANAKA    25
0002SUZUKI    30
0003SATOU     28

このファイルに対して、START文で特定の社員番号から読み込みを開始してみましょう。

ファイル作成用サンプルプログラム (WRITE)

以下のプログラムを実行してファイルを作成してください。

IDENTIFICATION DIVISION.
PROGRAM-ID. CREATE-SHAIN-FILE.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT SHAIN-FILE ASSIGN TO 'SHAIN.DAT'
           ORGANIZATION IS INDEXED
           ACCESS MODE IS SEQUENTIAL *> 最初は順番に書き込むのでSEQUENTIAL
           RECORD KEY IS SHAIN-BANGOU
           FILE STATUS IS FS-CODE.
DATA DIVISION.
FILE SECTION.
FD SHAIN-FILE.
01 SHAIN-RECORD.
   05 SHAIN-BANGOU   PIC X(4).
   05 SHAIN-NAME     PIC X(10). *> 日本語環境なら N(5) など調整
   05 SHAIN-AGE      PIC 9(2).
WORKING-STORAGE SECTION.
01 I                PIC 9(2) VALUE 1.  *> インデックス変数
01 FS-CODE          PIC X(2).
01 SHAIN-DATA-TABLE. *> 書き込むデータ
   05 FILLER         PIC X(16) VALUE '0001TANAKA    25'.
   05 FILLER         PIC X(16) VALUE '0002SUZUKI    30'.
   05 FILLER         PIC X(16) VALUE '0003SATOU     28'.
01 SHAIN-DATA REDEFINES SHAIN-DATA-TABLE.
   05 SHAIN-TABLE OCCURS 3 TIMES. *> 3件分のデータ領域
      10 IN-SHAIN-BANGOU   PIC X(4).
      10 IN-SHAIN-NAME     PIC X(10).
      10 IN-SHAIN-AGE      PIC 9(2).

PROCEDURE DIVISION.
MAIN-PROC.
    *> ファイルを書き込みモードで開く (新規作成)
    OPEN OUTPUT SHAIN-FILE.

    *> ファイル状態コードをチェック (OPENエラー)
    IF FS-CODE NOT = '00' AND FS-CODE NOT = '97' *> '97'は一部環境での新規作成成功コード
       DISPLAY 'FILE OPEN ERROR: ' FS-CODE
       GO TO END-PROC
    END-IF.

    *> テーブルのデータを順番にファイルへ書き込む
    PERFORM VARYING I FROM 1 BY 1 UNTIL I > 3
        MOVE IN-SHAIN-BANGOU(I) TO SHAIN-BANGOU
        MOVE IN-SHAIN-NAME(I)  TO SHAIN-NAME
        MOVE IN-SHAIN-AGE(I)   TO SHAIN-AGE

        WRITE SHAIN-RECORD
            INVALID KEY
                DISPLAY 'WRITE ERROR (INVALID KEY): ' FS-CODE ' KEY=' SHAIN-BANGOU
                GO TO CLOSE-PROC
        END-WRITE

        *> ファイル状態コードをチェック (WRITEエラー)
        IF FS-CODE NOT = '00'
           DISPLAY 'WRITE ERROR: ' FS-CODE ' KEY=' SHAIN-BANGOU
           GO TO CLOSE-PROC
        END-IF
    END-PERFORM.

    DISPLAY 'SHAIN.DAT CREATED SUCCESSFULLY.'.

CLOSE-PROC.
    *> ファイルを閉じる
    CLOSE SHAIN-FILE.

END-PROC.
    STOP RUN.

上の `CREATE-SHAIN-FILE` プログラムをコンパイルし、実行してください。

エラーなく完了すれば、実行場所に `SHAIN.DAT` が作成されます。これでSTART文を試す準備が整いました!

サンプルプログラム (START)

ファイルも準備できたので、いよいよSTART文を使ったプログラムです!

ここでは、「社員番号が '0002' 以上のレコードを全て読み込んで表示する」という処理を、START文を使って書いてみましょう。

IDENTIFICATION DIVISION.
PROGRAM-ID. START-SAMPLE.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT SHAIN-FILE ASSIGN TO 'SHAIN.DAT'
           ORGANIZATION IS INDEXED
           ACCESS MODE IS DYNAMIC *> STARTを使う場合DYNAMICかSEQUENTIAL
           RECORD KEY IS SHAIN-BANGOU
           FILE STATUS IS FS-CODE.
DATA DIVISION.
FILE SECTION.
FD SHAIN-FILE.
01 SHAIN-RECORD.
   05 SHAIN-BANGOU   PIC X(4).
   05 SHAIN-NAME     PIC X(10).
   05 SHAIN-AGE      PIC 9(2).
WORKING-STORAGE SECTION.
01 FS-CODE          PIC X(2).
01 START-KEY        PIC X(4) VALUE '0002'. *> 開始キー
01 EOF-FLAG         PIC X(1) VALUE '0'. *> ファイル終了フラグ
   88 EOF                     VALUE '1'.

PROCEDURE DIVISION.
MAIN-PROC.
    *> ファイルを読み込みモードで開く
    OPEN INPUT SHAIN-FILE.
    
    *> ファイル状態コードをチェック (OPENエラー)
    IF FS-CODE NOT = '00'
       DISPLAY 'FILE OPEN ERROR: ' FS-CODE
       GO TO END-PROC
    END-IF.

    *> 開始キーをセット
    MOVE START-KEY TO SHAIN-BANGOU. *> KEY IS句の比較対象と同じ項目にセット

    *> START文で読み込み開始位置を決める (キーが'0002'以上)
    START SHAIN-FILE
          KEY IS NOT LESS THAN SHAIN-BANGOU *> RECORD KEY項目を指定
          INVALID KEY
              DISPLAY 'START KEY NOT FOUND OR ERROR: ' FS-CODE
              SET EOF TO TRUE *> 開始位置が見つからなければ終了扱い
          NOT INVALID KEY
              DISPLAY 'START SUCCESS. READING FROM KEY: ' SHAIN-BANGOU
              *> 位置付け成功したら、最初のレコードを読み込む (READ NEXT)
              PERFORM READ-NEXT-RECORD
    END-START.

    *> ファイルの終わりまでレコードを読み込み表示するループ
    PERFORM UNTIL EOF
        DISPLAY 'READ DATA: ' SHAIN-BANGOU ' ' SHAIN-NAME ' ' SHAIN-AGE
        PERFORM READ-NEXT-RECORD
    END-PERFORM.

    GO TO CLOSE-PROC.

*> 次のレコードを読み込むサブルーチン
READ-NEXT-RECORD.
    READ SHAIN-FILE NEXT RECORD
         AT END SET EOF TO TRUE
    END-READ.
    IF NOT EOF AND FS-CODE NOT = '00'
        DISPLAY 'READ ERROR: ' FS-CODE
        SET EOF TO TRUE
    END-IF.

CLOSE-PROC.
    *> ファイルを閉じる
    CLOSE SHAIN-FILE.

END-PROC.
    STOP RUN.

サンプルプログラムの解説

このSTART文を使ったプログラム、少し長いですがポイントを絞って見ていきましょう。

  • ENVIRONMENT DIVISION
    • `ACCESS MODE IS DYNAMIC` になっています。START文を使う場合、キーによるランダムな位置付けと、その後の順次読み込みを組み合わせることが多いので `DYNAMIC` がよく使われます。(`SEQUENTIAL` でも使えますが、少し意味合いが異なります)。
    • `RECORD KEY IS SHAIN-BANGOU` で社員番号がキーであることを示しています。START文の `KEY IS` 句で比較するのは、このキー項目です。

  • DATA DIVISION
    • `START-KEY` として、読み込みを開始したいキーの値 ('0002') を用意しています。
    • `EOF-FLAG` は、ファイルの最後まで読み込んだかどうかを判定するためのフラグです。

  • PROCEDURE DIVISION
    • `OPEN INPUT SHAIN-FILE.` でファイルを開きます。今回は読み込むだけなので `INPUT` モードです。(更新もするなら `I-O` モード)
    • `MOVE START-KEY TO SHAIN-BANGOU.` ここが少し注意点。`START`文の `KEY IS` 句で使う比較対象のレコード項目(今回は `SHAIN-BANGOU`)に、あらかじめ比較したい値(`START-KEY`)を入れておく必要があります。
    • いよいよ `START SHAIN-FILE KEY IS NOT LESS THAN SHAIN-BANGOU ...` です! これで、「ファイル(SHAIN-FILE)の中で、レコードキー(SHAIN-BANGOU)の値が、今 `SHAIN-BANGOU` に入っている値 ('0002') 以上である最初のレコード」に、ファイルポインタ(読み込み位置)がセットされます。
    • `INVALID KEY` では、もし '0002' 以上のレコードが見つからなかった場合のエラー処理をしています。
    • `NOT INVALID KEY` (位置付け成功時)の中で、まず `PERFORM READ-NEXT-RECORD` を呼び出しています。START文で決めた位置にある最初のレコードを読み込むためです。
    • その後の `PERFORM UNTIL EOF ... END-PERFORM` ループで、ファイルが終わるまで `READ-NEXT-RECORD` を繰り返し呼び出し、読み込んだデータを表示しています。

  • READ-NEXT-RECORD サブルーチン
    • `READ SHAIN-FILE NEXT RECORD ...` という書き方になっています。これが「次のレコードを順番に読む」命令です。START文で位置を決めた後は、この `READ NEXT` で読み進めるのが定石です。
    • `AT END` は、もう次に読むレコードがない(ファイルの終わりに達した)場合に実行される処理です。ここで `EOF-FLAG` に '1' を立ててループを終了させます。

START文で「ジャンプ」して、READ NEXT で「順番に歩く」…そんなイメージでしょうか。この連携がSTART文を使う上でのポイントになりますね。

サンプルプログラムの実行結果

では、この `START-SAMPLE` プログラムをコンパイルして実行すると、どうなるでしょうか?
元の `SHAIN.DAT` はこうでした。

--- SHAIN.DAT (内容) ---
0001TANAKA    25
0002SUZUKI    30
0003SATOU     28

プログラムを実行すると、コンソールには以下のように表示されるはずです。

START SUCCESS. READING FROM KEY: 0002
READ DATA: 0002 SUZUKI    30
READ DATA: 0003 SATOU     28

見事に、社員番号 '0002' 以上のレコードだけ('0002' と '0003')が読み込まれて表示されていますね! 社員番号 '0001' のレコードはSTART文によってスキップされたわけです。これがSTART文の効果です。

COBOL START文を使う上での注意点

START文はファイルアクセスを効率化できますが、正しく使うためにはいくつか注意点があります。

ここでも、特に気をつけておきたいポイントを確認しましょう。

ファイルの種類とOPENモード

START文は、主に索引編成ファイル (INDEXED) や相対編成ファイル (RELATIVE) で意味を持ちます。 これらのファイルはキーや相対レコード番号でレコードの位置を特定できるため、START文による位置付けが可能です。

ファイルを開くモードは、`OPEN INPUT` (読み込み専用)または `OPEN I-O` (読み書き両用)である必要があります。`OPEN OUTPUT` (書き込み専用)や `EXTEND` (追記)モードではSTART文は使えません。

また、`ACCESS MODE` は `SEQUENTIAL` または `DYNAMIC` を指定します。`SEQUENTIAL` の場合は、主に読み込み途中で開始位置を変更したい場合などに使われますが、一般的にはキーを指定して任意の位置から始めたい場合は `DYNAMIC` が使われることが多いです。

KEY IS 句の条件指定

`KEY IS` 句で使う関係演算子 (`EQUAL TO`, `GREATER THAN`, `NOT LESS THAN` など) の選択は、実現したい処理に合わせて正確に選ぶ必要があります。

例えば、「'0002' を含む、それ以降」なら `NOT LESS THAN` (または `>=`) を使いますが、「'0002' より大きいものから」なら `GREATER THAN` を使います。この違いを意識しないと、意図したレコードが読み飛ばされたり、余計なレコードが含まれたりする原因になります。

また、比較対象となるデータ項目(サンプルでは `SHAIN-BANGOU` に `START-KEY` をMOVEしたもの)は、`SELECT`句で指定した `RECORD KEY` と型・桁数が一致している必要があります。ここが違うと、正しく比較できず、予期せぬ動作やエラーにつながります。

FILE STATUS句でのエラーチェック

これはファイル操作の基本ですが、START文の後も `FILE STATUS`句(サンプルでは `FS-CODE`)のチェックは欠かせません。

特に `INVALID KEY` が発生した場合、`FS-CODE` には何が原因で位置付けできなかったのかを示すコードが入ります(例: '23' はレコードが見つからなかった場合など)。

START文が成功したか (`FS-CODE` が '00' かどうか)、失敗したならなぜか、をきちんと確認する処理を組み込むことが、安定したプログラムには必要です。`INVALID KEY`句だけでなく、`NOT INVALID KEY`句の後でも、予期せぬファイル状態になっていないか確認すると、より堅牢になります。

START文とREAD文の関係

最後に、とても大事なポイントをもう一度。

START文は、あくまでファイル内の読み込み開始「位置」を決めるだけです。START文を実行しただけでは、データはプログラムに取り込まれません。
実際にデータを読み込むのは `READ` 文(通常は `READ NEXT`)の役割です。

START文で位置を決めた後、最初のレコードを読み込むためには、必ず `READ` (NEXT) 文を実行する必要があります。 サンプルプログラムで `NOT INVALID KEY` の直後に `PERFORM READ-NEXT-RECORD` をしていたのはそのためです。この連携を忘れないようにしましょう。

【まとめ】COBOLの「START文」を理解してファイルアクセスを効率化しよう!

今回は、ファイルの途中から読み込みを開始できる「START文」について、ファイルの準備から使い方、注意点まで見てきました。

ポイントをまとめてみましょう。

  • START文は、索引編成ファイルなどで、読み込み開始位置を決める(位置付けする)命令。
  • 基本的な書き方は `START ファイル名 KEY IS 関係演算子 データ項目名 ...`。
  • START文自体は読み込まず、その後の `READ NEXT` 文で実際の読み込みを行う。
  • `ACCESS MODE` は `DYNAMIC` や `SEQUENTIAL` で、`OPEN` は `INPUT` か `I-O` モードで使う。
  • `KEY IS`句の条件指定と、比較対象キー項目への値セットが正確に行われているか確認する。
  • 実行後は `FILE STATUS`句で成功・失敗を確認するのがお約束。

START文を使いこなせるようになると、大量のデータの中から必要な部分だけを効率的に処理できるようになり、プログラムのパフォーマンス向上にも繋がります。

最初はREAD文との関係が少しややこしく感じるかもしれませんが、サンプルを動かしたり、条件を変えて試したりしながら、ぜひSTART文の便利さを実感してみてください。

【関連記事】

>> 今さら聞けない「COBOLとは?」

このブログを検索

  • ()

自己紹介

自分の写真
リモートワークでエンジニア兼Webディレクターとして活動しています。プログラミングやAIなど、日々の業務や学びの中で得た知識や気づきをわかりやすく発信し、これからITスキルを身につけたい人にも役立つ情報をお届けします。 note → https://note.com/yurufuri X → https://x.com/mnao111

QooQ