The SEARCH statement lets you look through a table (a data structure defined with OCCURS) until a condition is true. You use WHEN to define what you are looking for and AT END to handle the case when nothing matches. For tables that are sorted by a key, SEARCH ALL does a binary search so the lookup is much faster. This page explains how to set up the table, run a search, and use the result.
Imagine a list of names. SEARCH walks down the list and checks each name. When it finds one that matches what you asked for (the WHEN condition), it stops and you can use that position. If it gets to the end and never finds a match, the AT END part runs so you can say "not found." SEARCH ALL is for when the list is in order (e.g. alphabetical): it can jump to the middle and narrow in, so it finds the answer in fewer steps.
| Statement | How it works | Table requirement | WHEN clause |
|---|---|---|---|
| SEARCH | Sequential search | Table can be in any order | One or more WHEN conditions |
| SEARCH ALL | Binary search | Table must be sorted by key | WHEN key = value (equality) |
The table must be defined with OCCURS and INDEXED BY an index name. The index is what SEARCH moves as it steps through the table. You do not give the index a PICTURE; the compiler defines it. Before the first SEARCH, set the index to 1 so the search starts at the first element (e.g. SET WS-IDX TO 1).
12345678910WORKING-STORAGE SECTION. 01 WS-TABLE. 05 WS-ENTRY OCCURS 100 TIMES INDEXED BY WS-IDX. 10 WS-CODE PIC X(3). 10 WS-NAME PIC X(20). 10 WS-AMOUNT PIC 9(5)V99. *> Before SEARCH, start at first element SET WS-IDX TO 1
SEARCH steps through the table from the current index position. For each element it evaluates the WHEN condition(s). When a WHEN is true, the statements after that WHEN run and the index (e.g. WS-IDX) points at the matching element. Then control leaves the SEARCH. If no WHEN is ever true, the AT END statements run.
123456789SET WS-IDX TO 1 SEARCH WS-ENTRY AT END MOVE "NOT FOUND" TO WS-MESSAGE SET WS-FOUND TO FALSE WHEN WS-CODE (WS-IDX) = WS-LOOKUP-CODE MOVE WS-NAME (WS-IDX) TO WS-RESULT-NAME SET WS-FOUND TO TRUE END-SEARCH.
In this example, WS-ENTRY is the table and WS-IDX is its index. We search for an entry where WS-CODE(WS-IDX) equals WS-LOOKUP-CODE. When found, we move the name to WS-RESULT-NAME. When not found, AT END sets a message and a flag.
You can code more than one WHEN. The search stops at the first WHEN that is true, and only that WHEN's statements run. So put the most likely or most important condition first if that helps. You can also combine conditions in one WHEN with AND or OR.
SEARCH ALL assumes the table is sorted by the key you are testing. It uses a binary search (split the range in half, compare, then narrow left or right), so it is much faster than SEARCH on large tables. The WHEN in SEARCH ALL must use an equality comparison on the key (e.g. WHEN WS-CODE (WS-IDX) = WS-LOOKUP-CODE). The table must be in ascending or descending order by that key.
12345678*> Table must be sorted by WS-CODE (ascending or descending) SET WS-IDX TO 1 SEARCH ALL WS-ENTRY AT END MOVE "NOT FOUND" TO WS-MESSAGE WHEN WS-CODE (WS-IDX) = WS-LOOKUP-CODE MOVE WS-NAME (WS-IDX) TO WS-RESULT-NAME END-SEARCH.
WS-NAME (WS-IDX)) if a WHEN was satisfied.1. Which clause runs when no WHEN condition is satisfied in a SEARCH?
2. For SEARCH to work, the table must be defined with: