TABLES

Table use within COBOL

TABLES in COBOL allow the programmer to access data that is set up in WORKING-STORAGE based on a code. As we have seen, it is more efficient to store a code on a file as opposed to storing the full description of the item. An example is the code for type of employee, F for full time, P for part time, C for consultant and T for temporary. Instead of storing the description of the employee, the programmer has stored the code. Letter codes can be used to access a table using a search methodology, but for now we are going to discuss simple tables and simple tables need numeric codes starting at the beginning of the number sequence without gaps. In previous examples, the programmer has converted the code into the name by using level 88s or by using decision making. This example presents another option: using the code to access the table and retrieve the name associated with the code.

To illustrate, we are going to change the employee type code on the input file to a numeric field and make 1 the code for full time, 2 the code for part time, 3 the code for consultant and 4 the code for temporary.

FD  INPUT-FILE.
01  INPUT-REC.
    05  EMP-TYPE-CODE     PIC 9.
Tables are set up so that the EMP-TYPE-CODE of 1 will access the first element in the table, the EMP-TYPE-CODE of 2 will access the second element in the table etc. The setup of the table needed in this example would start like this:
	01  EMPLOYEE-TABLE.
	    05  FILLER   PIC X(10)     VALUE "FULL TIME ".
	    05  FILLER   PIC X(10)     VALUE "PART TIME ".
            05  FILLER   PIC X(10)     VALUE "CONSULTANT".
            05  FILLER   PIC X(10)     VALUE "TEMPORARY ".
There are a couple of things you should notice:
To turn the list of names into a table, the programmer first needs to REDEFINE the list of elements or VALUEs shown in the example above. In the redefinition, the programmer will use the OCCURS clause to tell how many occurrences there are of the elements or VALUES defined in the original table layout. In our example there are 4 different elements and therefore 4 different occurrences. The OCCURS clause is what makes a TABLE. In defining the number of occurrences, each occurrence or element is given the same field name.
	01  EMPLOYEE-TABLE.
	    05  FILLER   PIC X(10)     VALUE "FULL TIME ".
	    05  FILLER   PIC X(10)     VALUE "PART TIME ".
            05  FILLER   PIC X(10)     VALUE "CONSULTANT".
            05  FILLER   PIC X(10)     VALUE "TEMPORARY ".
	01  RDF-EMPLOYEE-TABLE REDEFINES EMPLOYEE-TABLE
	    05  TYPE-EMP PIC X(10) OCCURS 4 TIMES.
The reason for making each field ten characters long becomes clearer when we look at the redefinition. The occurs clause says there are 4 elements and the picture says each of these elements is 10 characters long. The data in memory was set up like this in the original EMPLOYEE-TABLE.
	FULL TIME PART TIME CONSULTANTTEMPORARY
When it is divided by the redefines, think of it as COBOL going and counting 10 characters and putting a marker to say this is the first occurrence of TYPE-EMP and then going in ten more characters and putting another marker and saying this is the second occurrence of TYPE-EMP etc.
 	FULL TIME |PART TIME |CONSULTANT|TEMPORARY |
If the data had been set up as simply the length of the fields, the redefinition would be wrong, for example:
Invalid definition:      FULL TIMEPART TIMECONSULTANTTEMPORARY
Using the redefinition:  FULL TIMEP|ART TIMECO|NSULTANTTE|MPORARY
In the invalid definition above, you can see the problem if each field is not 10 characters long, the redefinition is taking 10 character groupings so the results will be garbage.

Looking at the redefinition, it is clear that each element is given the same name TYPE-EMP and that since TYPE-EMP OCCURS 4 TIMES there are essentially 4 fields called TYPE-EMP. This presents a problem, clearly if the programmer wrote a MOVE statement that said MOVE TYPE-EMP there would be an error condition because there are now four fields called TYPE-EMP and there is no way of knowing which one the programmer wants to move. The problem is solved with the use of a SUBSCRIPT. A SUBSCRIPT is essentially a pointer that will be used to tell which TYPE-EMP field needs to be moved. The SUBSCRIPT is written in parenthesis after the data name - remember, the data name we are talking about here is the data name that occurs. For example, to move the elements from the table to a field on the printline called TYPE-EMP-PR, the following statements could be used:

To move the first element in the table:       MOVE TYPE-EMP (1) TO TYPE-EMP-PR.
To move the second element in the table:      MOVE TYPE-EMP (2) TO TYPE-EMP-PR.
To move the third element in the table:       MOVE TYPE-EMP (3) TO TYPE-EMP-PR.
To move the fourth element in the table:      MOVE TYPE-EMP (4) TO TYPE-EMP-PR.
This is not very practical, in actual code, so instead of using the number of the element as the SUBSCRIPT, the programmer uses a field that contains the code that is to be the SUBSCRIPT. In our example, that field is the EMP-TYPE-CODE that is on the input file. The move statement would be:
	MOVE TYPE-EMP (EMP-TYPE-CODE) TO TYPE-EMP-PR.
If EMP-TYPE-CODE is 1 then the first element from the table (FULL TIME) will be moved to the field on the printline, if the EMP-TYPE-CODE is 2 then the second element from the table (PART TIME) will be moved to the field on the printline. Following this pattern, if the SUBSCRIPT is 3 then CONSULTANT will be accessed and moved and 4 will result in TEMPORARY being accessed and moved.

This is a limited example using a SUBSCRIPT with only 4 possible codes, however if there were 25 codes, it is clear that the table approach puts the main burden on the definition in Working-Storage and allows for a very straight forward coding structure in the Procedure Division.

In should be noted that TABLES in COBOL are frequently called ARRAYS in other languages.

To further clarify the concept of tables, other examples are illustrated below:

EXAMPLE #1:

The first example is five departments in a clothing store: MENS, WOMENS, INFANTS, GIRLS, BOYS. Instead of carrying the name of the department on the file, a code number will be assigned to each name and that code number will be carried on the file. In our example, MENS will have a code of 1, WOMENS will have a code of 2, INFANTS will have a code of 3, GIRLS will have a code of 4 and BOYS will have a code of 5. Since the longest of these names is INFANTS at 7 characters, each of the elements in the table will be 7 characters long.

01  DEPT-NAM-TABLE.
    05  FILLER    PIC X(7)    VALUE  "MENS   ".
    05  FILLER    PIC X(7)    VALUE  "WOMENS ".
    05  FILLER    PIC X(7)    VALUE  "INFANTS".   
    05  FILLER    PIC X(7)    VALUE  "GIRLS  ". 
    05  FILLER    PIC X(7)    VALUE  "BOYS   ".
01  RDF-DEPT-NAM-TABLE REDEFINES DEPT-NAM-TABLE.
    05  DEPT-NAM  PIC X(7) OCCURS 5 TIMES.
In this example, there is a field on the input called DEPT-NO which will be used as the SUBSCRIPT or pointer to take the correct DEPT-NAM from the table and move it to the print line.
FD  INPUT-FILE...
01  INPUT-REC.
    05  DEPT-NO     PIC 9.
In the paragraph or routine where the programmer wants to move the correct department name from the table to a field on the printline, the input field DEPT-NO is the pointer or SUBSCRIPT. The move statement will be:

	MOVE DEPT-NAM (DEPT-NO) TO DEPT-NAM-PR. 
This will work fine as long as we are guaranteed that the data has been edited and that there will be no number other than 1 through 5 in DEPT-NO. If there is a danger of DEPT-NO being non-numeric or a number other than 1, 2, 3, 4, or 5, the programmer should include a validity check, because if the subscript is 0 or the subscript is greater than the number in the OCCURS clause or if the subscript is non-numeric, the program will ABORT. One way to do this is to use a level 88 with the DEPT-NO field:

            05  DEPT-NO     PIC 9.
                88   VALID-DEPT-NO   VALUE 1 THRU 5.
Then in the routine that moves the department name, the programmer can code the following:
	   IF VALID-DEPT-NO
	      MOVE DEPT-NAM (DEPT-NO) TO DEPT-NAM-PR.
This could also be handled without the level 88, by asking the specific questions in the test for a valid DEPT-NO:
      IF DEPT-NO IS NUMERIC
          IF DEPT-NO > 0 AND DEPT-NO < 6
		    MOVE DEPT-NAM (DEPT-NO) TO DEPT-NAM-PR
          ELSE
              MOVE "INVALID" TO DEPT-NAM-PR
      ELSE
          MOVE "NOT #  " TO DEPT-NAM-PR.
An alternative, but not recommended, way to set up the table used in this example is shown below:
    01  DEPT-NAM-TABLE.
        05  FILLER    PIC  X(35)  
			VALUE "MENS   WOMENS INFANTSGIRLS  BOYS   ".
    01  RDF-DEPT-NAM-TABLE REDEFINES DEPT-NAM-TABLE.
        05  DEPT-NAM  PIC X(7)      OCCURS 5 TIMES.
CAUTION: The literal in the value clause cannot be more than 120 characters.

The data can be set up in any way as long as there is a stream of 35 characters that when divided into 5 groups of 7 characters each makes sense. Another example could be:
    01  DEPT-NAM-TABLE.
        05  FILLER    PIC X(14)   VALUE "MENS   WOMENS ".
        05  FILLER    PIC X(21)   VALUE "INFANTSGIRLS  BOYS   ".
    01  RDF-DEPT-NAM-TABLE REDEFINES DEPT-NAM-TABLE.
        05  DEPT-NAM  PIC X(7)  OCCURS 5 TIMES.
NOTE: In each of these table setups, the field that OCCURS is called DEPT-NAM, therefore any of the MOVE statements issued in the example above would work equally well with any of the table setups.

EXAMPLE #2:

The second example involves setting up numeric data in the table. For example, lets assume that we have the following information:
		Item #		Price

		   1		$50.00
		   2            $35.95
                   3            $25.99
                   4            $19.99
                   5            $ 9.95
                   6            $ 5.00

	The item number comes in on the input:  05  ITEM-NO   PIC 9.
The programmer need to set up a price table so that the price can be extracted from the table and printed on the printline. Since the programmer may want to use the price in calculations, it must be stored as an unedited numeric field. Therefore, the $ will not be used. Remember, when the programmer sets up constants, and the prices will be constants in the price table, the decimal point is included to align correctly with the V in the picture clause. Looking at the pricing information above, it is clear that each price should have room for two whole numbers and two decimal numbers, so the price should be defined as 99V99. Note also that since these are numeric constants, there are no quotes around the VALUE leading zero has been included when the data did not include a digit in the tens position.
	01  PRICE-TABLE.
	    05  FILLER		PIC 99V99		VALUE 50.00.
            05  FILLER		PIC 99V99		VALUE 35.95.
	    05  FILLER          PIC 99V99		VALUE 25.99.
	    05  FILLER		PIC 99V99 	        VALUE 19.99.
	    05  FILLER		PIC 99V99		VALUE 09.95.
            05  FILLER          PIC 99V99               VALUE 05.00.
	01  RDF-PRICE-TABLE REDEFINES PRICE-TABLE.
	    05  PRICE       PIC 99V99   OCCURS 6 TIMES.
Using this table and the code on the input (ITEM-N0), the programmer can move the item price to the printline using the following MOVE statement.
	MOVE PRICE (ITEM-NO) TO PRICE-PR.
PRICE-PR could be defined as an edited field on the printline with the picture of ZZ.99 or $ZZ.99 depending on how the programmer wanted to print the price.

An alternative way of setting up the table takes advantage of the fact that the table is a redefinition of the original data setup:
	01  PRICE-TABLE.
	    05  FILLER		PIC 9(4)	VALUE 5000.
            05  FILLER		PIC 9(4)	VALUE 3595.
	    05  FILLER          PIC 9(4)	VALUE 2599.
	    05  FILLER		PIC 9(4) 	VALUE 1999.
	    05  FILLER		PIC 9(4)	VALUE 0995.
            05  FILLER          PIC 9(4)        VALUE 0500.
	01  RDF-PRICE-TABLE REDEFINES PRICE-TABLE.
	    05  PRICE       PIC 99V99   OCCURS 6 TIMES.
In this example, the original numbers were setup as whole numbers. When the redefinition is done to turn the data into a table, an alternative way of looking at the data is presented by giving the picture of 99V99. When the data is used by means of referring to PRICE, the picture of 99V99 will be used which will assume a decimal place between the second and third digits.
PRICE from the table can be used in other ways, For example PRICE could be multiplied by the field NUMBER-SOLD to get the answer WORTH-WS.
	MULTIPLY PRICE(ITEM-NO) BY NUMBER-SOLD
	    GIVING WORTH-WS.

Example #3:

Suppose that you want to store the department name, and the manager name in the same table so that when you access the table using the department number from the input record as a subscript, you can get the information to print out both the department name and the manager name. To do this, the programmer can put two pieces of information in the table as a unit.

Subscript on the input record: 05 DEPT-NO PIC 9.

01  DEPARTMENT-TABLE
    05  FILLER  PIC X(17)   VALUE  "MENS    SMITH     ".
    05  FILLER  PIC X(17)   VALUE  "WOMENS  JOHNSON   ".
    05  FILLER  PIC X(17)   VALUE  "INFANTS LEE       ".   
    05  FILLER  PIC X(17)   VALUE  "GIRLS   HALL      ". 
    05  FILLER  PIC X(17)   VALUE  "BOYS    WILLIAMSON".
01  RDF-DEPARTMENT-TABLE REDEFINES DEPARTMENT-TABLE.
    05  DEPT-GROUP  OCCURS 5 TIMES.
        10  DEPT-NAME      PIC X(7).
	10  MANAGER-NAME   PIC X(10).
In this table the department name and manager have been grouped together at each 05 level. In setting up the VALUE clause, the programmer had to determine the longest department name (in this case INFANTS at 7 characters) and the longest manager name (in this case WILLIAMSON at 10 characters). This means that each PIC is the sum of these lengths or 17 characters. It also means that the department name uses the first 7 characters and the manager name uses the last 10 characters. The manager name must start in position 8.

When the table is redefined, the department name and manager name are grouped as DEPT-GROUP and the OCCURS clause tells that there are 5 of these groups (one group for each of the 05 levels in the original data above the redefines). Because the programmer needs access to the department name and manager name individually to move them to different fields on the printline, DEPT-GROUP is broken down into two parts:

DEPT-NAME is the first 7 characters of DEPT-GROUP and MANAGER-NAME is the next 10 characters of DEPT-GROUP.

The programmer can now use the DEPT-NO on the input record to move the DEPT-NAME and the MANAGER-NAME to fields on the printline using the following MOVES:
	MOVE DEPT-NAME (DEPT-NO) TO DEPT-NAME-PR.
 	MOVE MANAGER-NAME (DEPT-NO) TO MANAGER-NAME-PR.
If DEPT-NO is 2, the DEPT-NAME will be WOMENS and the MANAGER-NAME will be JOHNSON. These two fields will be moved to the printline.
If the DEPT-NO is 5, the DEPT-NAME will be BOYS and the MANAGER-NAME will be WILLIAMSON. These two fields will be moved to the printline.

Example #4:

The company gives a pay bonus depending on job category. The job category code comes in as a number from 1 to 3 on the input record. The table to give the name of the job category and the amount of the bonus is set up in WORKING-STORAGE. Using the job category code the programmer needs to move the job category and the amount of the bonus to the print line.
Input:          05  JOB-CODE   PIC 9.

Line:		01  PRINTZ.
              ...
                    05  JOB-CATEGORY-PR PIC X(17).  
		    05  FILLER          PIC X(10).
                    05  BONUS-PR        PIC $Z,ZZZ.99.

Table in WORKING-STORAGE.

01  JOB-BONUS-TABLE.
    05  FILLER  PIC X(23)  VALUE "UPPER MANAGEMENT 300000".
    05  FILLER  PIC X(23)  VALUE "MIDDLE MANAGEMENT200000".
    05  FILLER  PIC X(23)  VALUE "SUPPORT          100000".
01  RDF-JOB-BONUS-TABLE REDEFINES JOB-BONUS-TABLE.
    05  JOB-GROUP OCCURS 3 TIMES.
        10  JOB-CATEGORY   PIC X(17).
        10  BONUS          PIC 9(4)V99.

Move statements:

	MOVE JOB-CATEGORY (JOB-CODE) TO JOB-CATEGORY-PR.
	MOVE BONUS (JOB-CODE) TO BONUS-PR.
Since BONUS is part of an X field in the original data layout, notice that there is no decimal point in the data. The BONUS data is coded as if it were a whole number. When the table is redefined, the programmer has the opportunity to redefine the way those 6 numeric characters that comprise bonus are defined. This redefinition allows the PIC of 9999V99 thereby putting the assumed decimal point between the fourth and the fifth characters. The programmer could not have put a decimal point in the original data that was a part of the X picture or it would not have been interpreted correctly.