Searching a Table
The tables that we have looked at have all involved extracting information from the table 
using a pointer or subscript that was defined on the input.  The subscript was a numeric 
field with numbers starting at 1 that could be used to point to an item in the table.  This 
kind of subscript is called a DIRECT SUBSCRIPT meaning that the subscript as it is defined 
can be used as a direct pointer to extract data from the table.
  
If the program is dealing with data that requires a table, but there is no field that can 
be used as a DIRECT SUBSCRIPT, then it is necessary for the programmer to define a table 
that can be SEARCHed using an INDIRECT SUBSCRIPT.
Indirect subscript and a search
The following example sets up a situation where a DIRECT SUBSCRIPT is inappropriate, so the 
programmer must SEARCH the table using an INDIRECT SUBSCRIPT  as the pointer.  The search 
that is needed can be done with the SEARCH VERB or with code developed by the programmer.  
Some COBOL compilers do not support the SEARCH VERB and sometimes the search is too complex 
to use the verb, therefore a programmer must be able to use their own code to develop a 
search.  Since understanding the COBOL search code is critical to understanding the concept, 
the SEARCH VERB will be dealt with last.
This example will deal with a information that is to be set up in a table so that the 
programmer can use the item number on the input to retrieve the item name from the table 
and print it on the detail line.  The programmer is provided with the following list 
showing what item number goes with what item name:
| Item Number | Item Name | 
|---|
| 03 | SEAFOOD CHOWDER | 
| 12 | CORN CHOWDER | 
| 15 | CLAM CHOWDER | 
| 17 | TOMATO SOUP | 
| 24 | CHICKEN SOUP | 
| 25 | VEGETABLE SOUP | 
| 27 | ONION SOUP | 
| 28 | GREEN PEA SOUP | 
| 45 | WONTON SOUP | 
In this example, the item numbers are spread out rather than clustered at the beginning of 
the number sequence.  The item number cannot be used as a DIRECT SUBSCRIPT.  Instead, after 
setting up the table in Working-Storage, the programmer must write code to search the table 
using an INDIRECT SUBSCRIPT.  Because the search will involve comparing the item number on 
the input to the item number in the table, the item number must be included with the item 
name in the table that is set up.  Notice that this is a major difference from a table 
where a DIRECT SUBSCRIPT can be used.  In those tables the item number would not have been 
included in the table.
The approach is to read the item number on the input and compare it to the first item 
number entry in the table which in our example is 03, if it does not match, we move down 
and compare the item number on the input to the second item number entry in the table which 
in our example is 12.  This pattern continues until either a match is found or there are no 
more table entries to check.  To do this, we need to set up a subscript or pointer in the 
WORKING-STORAGE SECTION that we can use to point to the first entry in the table and then 
the second etc.  We also need to set up an indicator to tell us whether or not the search 
was successful.
FILE SECTION.
FD  INPUT-FILE.
01  INPUT-REC.
    ...
    05  ITEM-NUMBER-IN   PIC 99.
    ...
WORKING-STORAGE SECTION
01  SUBSCRIPTS.
    05  ITEM-SUB      PIC 99      VALUE 0.
01  INDICATORS.
    05  MATCH-IND     PIC XXX     VALUE "NO ".
Next, lets look at the table or tables that the programmer will need to set up in the 
WORKING-STORAGE SECTION.  Remember, the item number must be kept in the table so that the 
program can compare it to the item number on the input.  Clearly, the item number is also 
in the table since the purpose of the table is to access the item name and print it on the 
line.  The programmer can either establish one table containing both the item number and 
the item name or two tables, one containing the item number and one containing the item 
name.  My very strong preference is to establish one table containing both, but I will 
cover both approaches.  Note that the search and processing in the PROCEDURE DIVISION are 
the same no matter which setup method is chosen.
01  TABLE-COMBINED.
    05  FILLER    PIC X(17)  VALUE "03SEAFOOD CHOWDER".
    05  FILLER    PIC X(17)  VALUE "12CORN CHOWDER   ".
    05  FILLER    PIC X(17)  VALUE "15CLAM CHOWDER   ".
    05  FILLER    PIC X(17)  VALUE "17TOMATO SOUP    ".
    05  FILLER    PIC X(17)  VALUE "24CHICKEN SOUP   ".
    05  FILLER    PIC X(17)  VALUE "25VEGETABLE SOUP ".
    05  FILLER    PIC X(17)  VALUE "27ONION SOUP     ".
    05  FILLER    PIC X(17)  VALUE "28GREEN PEA SOUP ".
    05  FILLER    PIC X(17)  VALUE "45WONTON SOUP    ".
01  RDF-TABLE-COMBINED REDEFINES TABLE-COMBINED.
    05  ENTRIES   OCCURS 9 TIMES.
        10  ITEM-NUMBER-TBL      PIC 99.
        10  ITEM-NAME-TBL        PIC X(15).
With this method, the item number is stored right next to the item name so it is easy to see
 which number goes with which name.
  
Notice what happens when the table is redefined.  The 05 level indicates that there are 9 
entries and on the 10 level each entry is broken down so that the first two characters are 
given the name ITEM-NUMBER-TBL and the last 15 characters are given the name ITEM-NAME-TBL. 
This means that the item number and the item name can be accessed separately (ENTRIES 
accesses the combined data).
The other approach to setting up this information uses two tables:  one for item number and 
one for item name.
01  TABLE-ITEM-NUMBERS.
    05  FILLER    PIC 99  VALUE 03.
    05  FILLER    PIC 99  VALUE 12.
    05  FILLER    PIC 99  VALUE 15.
    05  FILLER    PIC 99  VALUE 17.
    05  FILLER    PIC 99  VALUE 24.
    05  FILLER    PIC 99  VALUE 25.
    05  FILLER    PIC 99  VALUE 27.
    05  FILLER    PIC 99  VALUE 28.
    05  FILLER    PIC 99  VALUE 45.
01  RDF-TABLE-ITEM-NUMBERS REDEFINES TABLE-ITEM-NUMBERS.
    05  ITEM-NUMBER-TBL      PIC 99   OCCURS 9 TIMES.
01  TABLE-NAMES.
    05  FILLER    PIC X(15)  VALUE "SEAFOOD CHOWDER".
    05  FILLER    PIC X(15)  VALUE "CORN CHOWDER   ".
    05  FILLER    PIC X(15)  VALUE "CLAM CHOWDER   ".
    05  FILLER    PIC X(15)  VALUE "TOMATO SOUP    ".
    05  FILLER    PIC X(15)  VALUE "CHICKEN SOUP   ".
    05  FILLER    PIC X(15)  VALUE "VEGETABLE SOUP ".
    05  FILLER    PIC X(15)  VALUE "ONION SOUP     ".
    05  FILLER    PIC X(15)  VALUE "GREEN PEA SOUP ".
    05  FILLER    PIC X(15)  VALUE "WONTON SOUP    ".
01  RDF-TABLE-NAMES REDEFINES TABLE-NAMES.
    05  ITEM-NAME-TBL        PIC X(15)   OCCURS 9 TIMES.
After the table or tables have been set up, the entries in the WORKING-STORAGE SECTION are 
complete.  The next step is to code the two PROCEDURE DIVISION routines: one routine that 
will control the search and direct the processing steps after the search is complete 
depending on whether or not the search was successful and one routine that will actually 
do the search.
Search
In the B-200-LOOP, when you are setting up the print line, you need the item name to move 
to the print line.  The item name is contained in the table, so you must search the table 
to find a match to the item number on the input and then move the corresponding item name 
to the print line.  Before doing the search, some preliminary housekeeping must be done.  
The subscript being used for the search must be set to 1 and the MATCH-IND used to tell 
whether a match was found is set to NO.  The search is performed until either the subscript 
is greater than 9 which indicates that all 9 elements in the table have been checked 
without finding a match or until the MATCH-IND is set to YES.   When the search is over, 
the program needs to know what condition triggered the end of the search (MATCH-IND = "YES" 
or ITEM-SUB >9).  If a match was found, the corresponding name will me moved from the table 
to the print line.  This will be done using ITEM-SUB.  If the match was found when ITEM-SUB 
= 4 then the statement MOVE ITEM-NAME-TBL (ITEM-SUB) will move the 4th name in the table.  
If a match was not found then an error message defined in WORKING-STORAGE will be moved.
The search itself happens in B-300-SEARCH.  The search compares the item number on the 
input to the item number in the table that the ITEM-SUB subscript is pointing to.  If the 
two numbers match, then the MATCH-IND is set to YES.  If the two numbers do not match, the 
ITEM-SUB is increased by one so that the next time this paragraph is performed the subscript 
will point down one item.
Notice that every time the perform is done, the UNTIL clause will check to see if the 
subscript has passed the limit of 9.  If the limit were passed, the subscript would be out 
of bounds or out of the range of the table and the program would about.  When working with 
tables, the programmer needs to always keep control of the subscript so that it never goes 
out of the range of the table.
The code for the search:
B-200-LOOP.
    ...
    ... processing not related to search ...
    ...
    MOVE 1 TO ITEM-SUB.
    MOVE "NO " TO MATCH-IND.
    PERFORM B-300-SEARCH
        UNTIL ITEM-SUB > 9 OR MATCH-IND = "YES".
    IF MATCH-IND = "YES"
        MOVE ITEM-NAME-TBL (ITEM-SUB) TO ITEM-NAME-PR
    ELSE
        MOVE ERROR-MSG-TBL TO ITEM-NAME-PR.
    ...
    ... processing not related to search...
    ...
B-300-SEARCH.
    IF ITEM-NUMBER-IN = ITEM-NUMBER-TBL (ITEM-SUB)
        MOVE "YES" TO MATCH-IND
    ELSE
        ADD 1 TO ITEM-SUB.
The B-200-LOOP includes the code to:
- set up the search - (1) set the search subscript in Working Storage that 
will successively point to each element in the table to 1 and (2) initialize the match 
indicator that will tell whether or not the search was successful to NO
- perform the search - perform the search routine which checks an item in 
the table until either a match is found (set the match indicator to YES) or all of the 
items in the table have been checked
- process according to the outcome of the search - the search is terminated 
either by a match being found, in which case the match indicator will be set to YES or by 
all of the elements in the table being checked - when the search is over, the indicator 
will tell what caused it to end - if the indicator has been set to YES then the search was 
successful and the processing that should be done if a match was found is executed - if the 
indicator has stayed NO, the search was not successful and error processing should be 
executed
The B-300-SEARCH includes the code to:
- Check for a match between the input and the items in the table - this 
routine checks the item number on the input (ITEM-NUMBER-IN) against one of the item 
numbers in the table (ITEM-NUMBER-TBL).  Each time this routine is executed it will 
compare to a different item number in the table.  This is accomplished by using ITEM-SUB 
which starts at 1 and is increased by one every time this routine is executed
- Processing if match is found - if a match is found, the match indicator 
is set to YES - this accomplishes two things: (1) the routine will not be executed again 
since one of the conditions that terminates the perform is MATCH-IND = "YES" and (2) it 
will indicate that the search was successful and trigger appropriate processing
- Processing if match is not found - if a match is not found, ITEM-SUB is 
increased by 1 so that the next time through the B-300-SEARCH the comparison will be with 
the next item in the table
Notice that the B-300-SEARCH is being performed until one of two conditions is met and 
that both these conditions are changed in the B-300-SEARCH routine itself.  In other words, 
the MATCH-IND can be changed to YES if a match is found and the ITEM-SUB is increased by 1 
each time that a match is not found.  This is a very important point to understand.  
The perform of the routine is done until one of two conditions is met and these conditions 
both can change within the routine that is being performed so that the perform will 
eventually terminate.