COBOLの「SEARCH文」とは?基本構文から使い方まで初心者向けに解説

2025年4月10日木曜日

COBOL

COBOLでたくさんのデータが詰まったテーブルの中から、目的のデータを探し出す時、どうしていますか?

一つ一つ順番に見ていくのも良いですが、もっと効率的な方法があるんです。それが、COBOLが用意してくれている便利な命令、「SEARCH文」なんです!

でも、「SEARCH文ってなんだか難しそう…」「SEARCHとSEARCH ALLって何が違うの?」なんて、ちょっと尻込みしちゃう気持ち、すごく分かります。

大丈夫、心配いりません!この記事を読めば、SEARCH文の「?」が「!」に変わるはずです。

さあ、一緒にSEARCH文の世界を探検してみましょう! きっとあなたのCOBOLスキルが一段階レベルアップしますよ!

この記事で学べること

  • SEARCH文がどんな時に役立つか
  • SEARCH文の基本的な書き方のルール
  • 逐次サーチ(SEARCH)と二分探索サーチ(SEARCH ALL)の違いと使い方
  • SEARCH文を使うためのテーブル定義の方法
  • 実際に動かせるサンプルコードとその解説
  • SEARCH文を使う時に気をつけたいポイント

COBOLの「SEARCH文」とは?テーブル検索の基本を理解しよう

まず、COBOLのSEARCH文が一体何者なのか、その役割から見ていきましょう。

簡単に言うと、SEARCH文は「テーブル(配列)の中から、指定した条件に合うデータを見つけ出すための命令」です。

例えば、社員番号が100人分入ったテーブルから、「社員番号50番の人」のデータを探したい!なんて時。

もしSEARCH文がなかったら、プログラムで1番目から100番目まで順番に、「社員番号は50番かな?」と一つずつチェックしていくコードを書く必要があります。データが少なければそれでも良いのですが、何千、何万件とデータが増えたら大変ですよね?処理に時間もかかってしまいます。

そこで登場するのがSEARCH文!

SEARCH文を使えば、COBOLが効率的な方法でテーブル内を探してくれて、目的のデータが見つかったら教えてくれるんです。
まるで、広大な図書館の中から、目的の本を素早く見つけ出してくれる司書さんのようですね。

SEARCH文を使いこなせれば、プログラムの処理速度を上げることができ、スマートなコーディングが可能になりますよ。

「SEARCH文」の基本的な書き方(構文)

では、実際にSEARCH文をどうやって書くのか、基本的な形を見てみましょう。
細かいオプションは一旦置いておいて、まずは骨組みを掴むことが肝心です。

SEARCH テーブル名
    AT END
        見つからなかった時の処理
    WHEN 条件
        見つかった時の処理
END-SEARCH.

ざっくりと、こんな形になります。
それぞれの部分が何を意味するか、簡単に説明しますね。

  • SEARCH テーブル名
    「これから『テーブル名』という名前のテーブルを探しますよー!」という宣言です。
  • AT END
    テーブルの最後まで探したけど、結局条件に合うデータが見つからなかった…という場合に、ここ(AT ENDからWHENまでの間)に書かれた処理が実行されます。
  • WHEN 条件
    「こんな条件に合うデータを探してね!」という指定です。条件に合うデータが見つかったら、ここ(WHENからEND-SEARCHまでの間、または次のWHENまで)に書かれた処理が実行されます。
  • END-SEARCH
    「SEARCH文はここまでですよ」という終わりの合図です。

これがSEARCH文の基本的な構造です。

次は、もう少し具体的に、SEARCH文の2つの種類「逐次サーチ」と「二分探索サーチ」の書き方を見ていきましょう。

逐次サーチ(Sequential SEARCH)の構文

まずは「逐次サーチ」を行うSEARCH文です。

逐次サーチは、テーブルの先頭から順番に、一つずつ条件に合うかチェックしていく方法です。シンプルで分かりやすいですね。

書き方はこんな感じです。

SET 指標名 TO 1.  <-- 検索開始位置を先頭(1番目)にセット!

SEARCH テーブル名 VARYING 指標名
    AT END
        *> 見つからなかった時の処理をここに書く
        DISPLAY "データが見つかりませんでした。"
    WHEN テーブル要素(指標名) = 探したい値
        *> 見つかった時の処理をここに書く
        DISPLAY "データが見つかりました!"
        *> (必要なら見つかった要素に対する処理などを書く)
END-SEARCH.

いくつか新しい要素が出てきましたね。

  • SET 指標名 TO 1.
    これが超重要! 逐次サーチを始める前に、必ずテーブルのどこから探し始めるか(通常は先頭の1番目)を`SET`文で指定してあげる必要があります。これを忘れると、予期せぬ動きをしたり、エラーになったりするので注意してくださいね。`SET`文での指標の初期化は忘れずに!
  • VARYING 指標名
    SEARCH文がテーブルの中を移動していく際に、現在位置を示す「指標(インデックス)」を動かすための指定です。SEARCH文が内部で指標の値を増やしながら検索を進めてくれます。
  • テーブル要素(指標名) = 探したい値
    これが`WHEN`句の具体的な条件の書き方の一例です。「テーブルの『指標名』番目の要素が、『探したい値』と同じだったら」という意味になります。

逐次サーチは、テーブルのデータが順番に並んでいなくても使えますが、データ量が多いと時間がかかることがあります。

二分探索サーチ(SEARCH ALL)の構文

次にご紹介するのが「二分探索サーチ」、`SEARCH ALL`文です。
これは、逐次サーチよりもずっと高速に検索できる可能性がある、賢い方法なんです!

ただし、`SEARCH ALL`を使うには事前の準備が必要不可欠です。

それは、
「検索対象のテーブルが、検索キーとなる項目で、あらかじめ昇順(小さい順)または降順(大きい順)に並べ替えられていること」
です。これが守られていないと、正しく動作しません。

イメージとしては、辞書で単語を探す時、最初から順番にページをめくる(逐次サーチ)のではなく、真ん中あたりを開いて、目的の単語がそれより前にあるか後ろにあるか判断し、探す範囲をどんどん半分に絞っていく(二分探索サーチ)感じです。だから速いんですね!

書き方はこちら。

SEARCH ALL テーブル名
    AT END
        *> 見つからなかった時の処理をここに書く
        DISPLAY "データが見つかりませんでした。"
    WHEN キー項目(指標名) = 探したい値
        *> 見つかった時の処理をここに書く
        DISPLAY "データが見つかりました!"
        *> (必要なら見つかった要素に対する処理などを書く)
END-SEARCH.

逐次サーチの`SEARCH`と比べて、`SEARCH ALL`には`VARYING`句がありませんね。

また、`WHEN`句の条件で使う項目は、テーブル定義時に`ASCENDING KEY`または`DESCENDING KEY`として指定した「キー項目」である必要があります。(テーブル定義については後ほど説明しますね!)

そして、`SEARCH ALL`では、`SET`文による指標の初期化は不要です。COBOLが自動で効率的な検索を行ってくれます。

データ量が多い場合や、検索速度が求められる場合には、`SEARCH ALL`が非常に有効です。ただし、事前にテーブルをソートしておく手間がかかる点を覚えておきましょう。

「SEARCH文」を使うための準備:テーブル定義

さて、SEARCH文を使うには、まず検索対象となる「テーブル(配列)」をデータ部(DATA DIVISION)で定義しておく必要があります。

これは料理で言う「下ごしらえ」のようなもの。SEARCH文という調理器具を使うために、材料(データを入れる器=テーブル)を用意するイメージです。

テーブル定義で特にSEARCH文と関わりが深いのが、`OCCURS`句と`INDEXED BY`句です。

OCCURS句によるテーブル定義

`OCCURS`句は、「この項目を〇回繰り返しますよ」と指定するためのものです。
これを使うことで、同じ形のデータ項目を複数個まとめたテーブル(配列)を作ることができます。

例えば、社員データを100人分格納するテーブルを作りたい場合は、こんな風に書きます。

 DATA DIVISION.
 WORKING-STORAGE SECTION.
 01 SYAIN-TABLE.
    05 SYAIN-DATA OCCURS 100 TIMES. <-- ここ! SYAIN-DATAを100回繰り返す
       10 SYAIN-NO    PIC 9(5).      <-- 社員番号 (5桁の数字)
       10 SYAIN-NAME  PIC X(20).     <-- 氏名 (20桁の文字)

これで、`SYAIN-DATA`という社員1人分のデータ構造(社員番号と氏名)が100個並んだ`SYAIN-TABLE`というテーブルが用意できました。

テーブルの大きさを決める大切な句です。SEARCH文は、この`OCCURS`句で定義された範囲内を検索します。

INDEXED BY句による指標名の設定

次に`INDEXED BY`句です。これは、SEARCH文がテーブル内を移動(検索)する際に、「今、テーブルの何番目にいるのか」を示すための特別な変数(指標、インデックス)の名前を決めるものです。

先ほどのテーブル定義に`INDEXED BY`句を追加してみましょう。

 DATA DIVISION.
 WORKING-STORAGE SECTION.
 01 SYAIN-TABLE.
    05 SYAIN-DATA OCCURS 100 TIMES INDEXED BY SYAIN-INDEX. <-- ここ!
       10 SYAIN-NO    PIC 9(5).
       10 SYAIN-NAME  PIC X(20).

このように`INDEXED BY SYAIN-INDEX`と書くことで、`SYAIN-INDEX`という名前の指標が使えるようになります。

この指標名は、逐次サーチの`SET`文や`VARYING`句、そして`WHEN`句の条件で `テーブル要素(指標名)` のように使われます。

指標はSEARCH文の相棒のような存在で、`SEARCH`文を使うためには、原則として`INDEXED BY`句で指標名を指定しておく必要があります。

さらに! `SEARCH ALL`文を使いたい場合は、これに加えて、どの項目を検索キーにするかを指定する`ASCENDING KEY IS`句(昇順の場合)または`DESCENDING KEY IS`句(降順の場合)も必要になります。

 DATA DIVISION.
 WORKING-STORAGE SECTION.
 01 SYAIN-TABLE.
    05 SYAIN-DATA OCCURS 100 TIMES
                  ASCENDING KEY IS SYAIN-NO  <-- SEARCH ALL用のキー指定(昇順)
                  INDEXED BY SYAIN-INDEX.   <-- 指標名の指定
       10 SYAIN-NO    PIC 9(5).
       10 SYAIN-NAME  PIC X(20).

これで、`SYAIN-NO`(社員番号)をキーとして`SEARCH ALL`文が使えるようになりました!

「SEARCH文」の使い方

お待たせしました!いよいよ、実際にSEARCH文を使った簡単なプログラムを見ていきましょう。

百聞は一見に如かず、コードを動かしてみるのが一番の近道です。
ここでは、逐次サーチ(`SEARCH`)と二分探索サーチ(`SEARCH ALL`)の両方のサンプルを用意しました。

ぜひ、お手元の環境でコピーして試してみてくださいね。

逐次サーチ(SEARCH)のサンプルと実行結果

まずは、逐次サーチのサンプルです。

商品コード(`PRODUCT-CODE`)が3つの商品データ(`PRODUCT-DATA`)を持つテーブル(`PRODUCT-TABLE`)から、指定した商品コードを探します。

サンプルプログラム (Sequential Search)

IDENTIFICATION DIVISION.
PROGRAM-ID. SEQ-SEARCH-SAMPLE.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 SEARCH-CODE PIC X(3) VALUE "B01". *> 探したい商品コード
01 MSG         PIC X(60).

01 PRODUCT-TABLE.
   05 PRODUCT-DATA OCCURS 3 TIMES INDEXED BY P-INDEX.
      10 PRODUCT-CODE PIC X(3).
      10 PRODUCT-NAME PIC X(10).

PROCEDURE DIVISION.
*> テーブルにデータを設定 (サンプルなので直接値を設定)
   MOVE "A01" TO PRODUCT-CODE(1).
   MOVE "Apple" TO PRODUCT-NAME(1).
   MOVE "B01" TO PRODUCT-CODE(2).
   MOVE "Banana" TO PRODUCT-NAME(2).
   MOVE "C01" TO PRODUCT-CODE(3).
   MOVE "Cherry" TO PRODUCT-NAME(3).

*> 検索開始
   SET P-INDEX TO 1. *> 指標を初期化!
   SEARCH PRODUCT-DATA VARYING P-INDEX
       AT END
           MOVE "商品が見つかりませんでした。" TO MSG
       WHEN PRODUCT-CODE(P-INDEX) = SEARCH-CODE
           STRING "商品が見つかりました! Name:" DELIMITED BY SIZE
                  PRODUCT-NAME(P-INDEX)          DELIMITED BY SIZE
                  INTO MSG
   END-SEARCH.

*> 結果表示
   DISPLAY MSG.
   STOP RUN.

実行結果 (SEARCH-CODE が "B01" の場合)

商品が見つかりました! Name:Banana

実行結果 (SEARCH-CODE が "D01" の場合)

商品が見つかりませんでした。

コードのポイント

  • `WORKING-STORAGE SECTION`でテーブル`PRODUCT-TABLE`と指標`P-INDEX`を定義しています。`OCCURS 3 TIMES`で要素数は3つです。
  • `PROCEDURE DIVISION`の最初で、テーブルにサンプルデータを`MOVE`文で設定しています。
  • `SEARCH`文の前に、必ず`SET P-INDEX TO 1.`で指標を初期化しています。これが大事!
  • `WHEN`句で`PRODUCT-CODE(P-INDEX)`と`SEARCH-CODE`を比較し、一致したらメッセージを設定しています。見つかった要素の`PRODUCT-NAME(P-INDEX)`もメッセージに含めています。(この部分の`STRING`文も、前回の`SEARCH ALL`の例と同様の注意点があります。より安全な書き方は`SEARCH ALL`の修正例を参考にしてください。)
  • `AT END`句で、見つからなかった場合のメッセージを設定しています。

コード内のコメントも参考にしてくださいね。 逐次サーチの基本的な流れが掴めたでしょうか?

二分探索サーチ(SEARCH ALL)のサンプルと実行結果

続いて、二分探索サーチ(`SEARCH ALL`)のサンプルです。

今度は、社員番号(`SYAIN-NO`)でソートされた社員テーブル(`SYAIN-TABLE`)から、指定した社員番号を探します。(前回指摘のあった`STRING`文を修正済みです)

サンプルプログラム (Binary Search - 修正版)

IDENTIFICATION DIVISION.
PROGRAM-ID. BIN-SEARCH-SAMPLE-MOD.

DATA DIVISION.
WORKING-STORAGE SECTION.
01 SEARCH-NO PIC 9(5) VALUE 00015. *> 探したい社員番号
01 MSG       PIC X(60).

01 SYAIN-TABLE.
   05 SYAIN-DATA OCCURS 5 TIMES
                 ASCENDING KEY IS SYAIN-NO *> キー項目(昇順)を指定
                 INDEXED BY S-INDEX.      *> 指標を指定
      10 SYAIN-NO    PIC 9(5).
      10 SYAIN-NAME  PIC X(20).

PROCEDURE DIVISION.
*> テーブルにデータを設定 (昇順にソートされている必要がある!)
   MOVE 00005 TO SYAIN-NO(1). MOVE "Sato"      TO SYAIN-NAME(1).
   MOVE 00010 TO SYAIN-NO(2). MOVE "Suzuki"    TO SYAIN-NAME(2).
   MOVE 00015 TO SYAIN-NO(3). MOVE "Takahashi" TO SYAIN-NAME(3).
   MOVE 00020 TO SYAIN-NO(4). MOVE "Tanaka"    TO SYAIN-NAME(4).
   MOVE 00025 TO SYAIN-NO(5). MOVE "Watanabe"  TO SYAIN-NAME(5).

*> 検索開始 (SEARCH ALLではSETによる指標の初期化は不要)
   SEARCH ALL SYAIN-DATA
       AT END
           MOVE "社員が見つかりませんでした。" TO MSG
       WHEN SYAIN-NO(S-INDEX) = SEARCH-NO *> キー項目で比較!
           STRING "社員が見つかりました! Name:" DELIMITED BY SIZE
                  SYAIN-NAME(S-INDEX)       DELIMITED BY SIZE
                  INTO MSG
   END-SEARCH.

*> 結果表示
   DISPLAY MSG.
   STOP RUN.

実行結果 (SEARCH-NO が 00015 の場合)

社員が見つかりました! Name:Takahashi

実行結果 (SEARCH-NO が 00011 の場合)

社員が見つかりませんでした。

コードのポイント

  • テーブル定義で`ASCENDING KEY IS SYAIN-NO`と`INDEXED BY S-INDEX`が指定されています。これが`SEARCH ALL`の必須条件です。
  • テーブルに設定するデータは、必ず`SYAIN-NO`の昇順になるようにしています。(00005, 00010, 00015...)
  • `SEARCH ALL`文の前には、`SET`文による指標の初期化は書いていません。不要だからです。
  • `WHEN`句の条件では、キー項目として指定した`SYAIN-NO(S-INDEX)`と`SEARCH-NO`を比較しています。
  • `WHEN`句の処理を修正しました。`STRING`文で固定文字列と`SYAIN-NAME(S-INDEX)`を直接`MSG`に連結するように変更し、不要な`MOVE`文を削除(コメントアウト)しました。

逐次サーチとのコードの違いを見比べてみましょう。

特にテーブル定義と`SET`文の有無に注目してください。`SEARCH ALL`がいかに事前準備(ソートとキー指定)を前提としているかが分かりますね。

COBOLの「SEARCH文」を使う上での注意点

SEARCH文はとても便利ですが、いくつか気をつけておきたいポイントがあります。

特に初心者のうちは、思わぬエラーに繋がることもあるので、しっかり押さえておきましょう!

SEARCH ALLを使う際のキー項目のソート

これは`SEARCH ALL`を使う上で、絶対に守らなければならないルールです。

先ほども説明しましたが、`SEARCH ALL`文は、テーブルのデータが`ASCENDING KEY`または`DESCENDING KEY`で指定したキー項目に関して、きちんと昇順または降順にソート(整列)されていることを前提として動作します。

もし、ソートされていないテーブルに対して`SEARCH ALL`を使ってしまうと…

  • 探しているデータがあるはずなのに「見つからない」という結果になる。
  • 全く関係ないデータが「見つかった」ことになってしまう。
  • 場合によっては、プログラムが異常終了してしまう。

といった、予期せぬ結果を招きます。

なぜソートが必要かというと、`SEARCH ALL`(二分探索)は、「今の場所のキーの値」と「探している値」を比べて、「もっと前を探すべきか、後ろを探すべきか」を判断しながら検索範囲を絞り込んでいく仕組みだからです。データがバラバラの順番だと、この大小比較が正しく機能しないんですね。

ですから、`SEARCH ALL`を使う前には、必ずテーブルが正しくソートされているかを確認しましょう。もしソートされていない場合は、`SORT`文などを使って事前にソート処理を行う必要があります。ソートされていないと正しい結果が出ません!

【まとめ】COBOLの「SEARCH文」をマスターして効率的な検索を!

お疲れ様でした!今回はCOBOLのテーブル検索の強い味方、「SEARCH文」について、基本的な役割から、逐次サーチ(`SEARCH`)と二分探索サーチ(`SEARCH ALL`)の書き方、使い方、そして注意点まで、盛りだくさんで解説してきました。

もう一度、ポイントをおさらいしましょう。

  • SEARCH文はテーブルから効率的にデータを探す命令。
  • 逐次サーチ(`SEARCH`)は先頭から順番に探す。指標の初期化(`SET`)が必要。
  • 二分探索サーチ(`SEARCH ALL`)は高速だが、キー項目での事前ソートが必須。テーブル定義でキーと指標の指定が必要。
  • `OCCURS`句でテーブルの大きさを、`INDEXED BY`句で指標を定義する。
  • `SEARCH ALL`を使う前は、必ずソートされているか確認!

最初は少し複雑に感じるかもしれませんが、サンプルコードを実際に動かしてみたり、自分で簡単なプログラムを作ってみたりするうちに、きっとSEARCH文の便利さが実感できるはずです。
SEARCH文をマスターすれば、COBOLでのデータ処理がもっとスムーズに、そしてプログラムの品質もグッと向上しますよ。

この記事が、あなたのCOBOL学習の一助となれば、とても嬉しいです。
自信を持って、どんどんSEARCH文を使ってみてください!応援しています!

【関連記事】

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

このブログを検索

  • ()

自己紹介

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

QooQ