The OCCURS clause in COBOL is used to define tables (arrays) by specifying how many times a data item should be repeated. It enables the creation of homogeneous data structures that can be accessed using subscripts or indexes, providing powerful capabilities for processing lists, tables, and repetitive data structures in business applications.
*> Fixed OCCURS
level-number data-name OCCURS integer TIMES [clauses].
*> OCCURS DEPENDING ON
level-number data-name OCCURS min-times TO max-times TIMES
DEPENDING ON data-name-2 [clauses].
*> OCCURS with INDEXED BY
level-number data-name OCCURS integer TIMES
INDEXED BY index-name-1 [index-name-2 ...] [clauses].
*> OCCURS with KEY
level-number data-name OCCURS integer TIMES
[ASCENDING|DESCENDING] KEY IS data-name-3 [data-name-4 ...]
[INDEXED BY index-name-1 ...] [clauses].01 MONTHLY-SALES-TABLE.
05 MONTHLY-SALES OCCURS 12 TIMES PIC 9(7)V99.
01 STUDENT-GRADES.
05 GRADE-ENTRY OCCURS 50 TIMES PIC 999.
01 EMPLOYEE-TABLE.
05 EMPLOYEE-RECORD OCCURS 100 TIMES.
10 EMP-ID PIC 9(6).
10 EMP-NAME PIC X(25).
10 EMP-SALARY PIC 9(6)V99.
PROCEDURE DIVISION.
*> Accessing table elements
MOVE 15000.50 TO MONTHLY-SALES (1).
MOVE 18000.75 TO MONTHLY-SALES (12).
MOVE 85 TO GRADE-ENTRY (1).
MOVE 92 TO GRADE-ENTRY (25).
MOVE 123456 TO EMP-ID (1).
MOVE "JOHN SMITH" TO EMP-NAME (1).
MOVE 50000.00 TO EMP-SALARY (1).Basic table definitions with fixed occurrences.
01 SALES-MATRIX.
05 QUARTERLY-DATA OCCURS 4 TIMES.
10 MONTHLY-DATA OCCURS 3 TIMES.
15 DAILY-SALES OCCURS 31 TIMES PIC 9(6)V99.
01 GRADE-MATRIX.
05 CLASS-DATA OCCURS 10 TIMES.
10 STUDENT-DATA OCCURS 30 TIMES.
15 SUBJECT-GRADES OCCURS 5 TIMES PIC 999.
PROCEDURE DIVISION.
*> Accessing multi-dimensional elements
MOVE 1250.00 TO DAILY-SALES (1, 1, 1). *> Q1, Jan, Day 1
MOVE 1850.75 TO DAILY-SALES (4, 3, 31). *> Q4, Mar, Day 31
MOVE 95 TO SUBJECT-GRADES (1, 1, 1). *> Class 1, Student 1, Subject 1
MOVE 87 TO SUBJECT-GRADES (10, 30, 5). *> Class 10, Student 30, Subject 5Creating and accessing multi-dimensional table structures.
01 TRANSACTION-RECORD.
05 TRANS-COUNT PIC 99.
05 TRANSACTION-DETAILS OCCURS 1 TO 50 TIMES
DEPENDING ON TRANS-COUNT.
10 TRANS-TYPE PIC X(8).
10 TRANS-AMOUNT PIC 9(8)V99.
10 TRANS-DATE PIC 9(8).
01 INVOICE-DATA.
05 LINE-COUNT PIC 999.
05 INVOICE-LINES OCCURS 1 TO 999 TIMES
DEPENDING ON LINE-COUNT.
10 ITEM-CODE PIC X(15).
10 DESCRIPTION PIC X(40).
10 QUANTITY PIC 9(5).
10 UNIT-PRICE PIC 9(7)V99.
10 TOTAL-PRICE PIC 9(9)V99.
PROCEDURE DIVISION.
*> Setting up variable length tables
MOVE 5 TO TRANS-COUNT.
MOVE 25 TO LINE-COUNT.
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > TRANS-COUNT
MOVE "PURCHASE" TO TRANS-TYPE (WS-INDEX)
MOVE 100.00 TO TRANS-AMOUNT (WS-INDEX)
END-PERFORM.Using OCCURS DEPENDING ON for flexible table sizes.
01 CUSTOMER-ORDER.
05 ITEM-COUNT PIC 999.
05 ORDER-ITEMS OCCURS 1 TO 100 TIMES
DEPENDING ON ITEM-COUNT.
10 PRODUCT-ID PIC X(10).
10 PRODUCT-NAME PIC X(30).
10 ORDER-QTY PIC 9(5).
10 UNIT-COST PIC 9(6)V99.
01 WS-PROCESSING-DATA.
05 WS-INDEX PIC 999.
05 WS-TOTAL-COST PIC 9(10)V99.
05 WS-ITEM-TOTAL PIC 9(8)V99.
PROCEDURE DIVISION.
CALCULATE-ORDER-TOTAL.
MOVE ZERO TO WS-TOTAL-COST.
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > ITEM-COUNT
COMPUTE WS-ITEM-TOTAL = ORDER-QTY (WS-INDEX) *
UNIT-COST (WS-INDEX)
ADD WS-ITEM-TOTAL TO WS-TOTAL-COST
DISPLAY "ITEM " WS-INDEX ": " PRODUCT-NAME (WS-INDEX)
DISPLAY " QTY: " ORDER-QTY (WS-INDEX)
DISPLAY " COST: $" UNIT-COST (WS-INDEX)
DISPLAY " TOTAL: $" WS-ITEM-TOTAL
END-PERFORM.
DISPLAY "ORDER TOTAL: $" WS-TOTAL-COST.Processing variable length arrays with calculations.
01 PRODUCT-TABLE.
05 PRODUCT-ENTRY OCCURS 500 TIMES
INDEXED BY PROD-INDEX.
10 PROD-CODE PIC X(10).
10 PROD-NAME PIC X(25).
10 PROD-PRICE PIC 9(6)V99.
10 PROD-QUANTITY PIC 9(5).
01 CUSTOMER-TABLE.
05 CUSTOMER-ENTRY OCCURS 1000 TIMES
INDEXED BY CUST-INDEX.
10 CUST-ID PIC X(8).
10 CUST-NAME PIC X(30).
10 CUST-BALANCE PIC S9(8)V99.
PROCEDURE DIVISION.
SEARCH-PRODUCT-TABLE.
SET PROD-INDEX TO 1.
SEARCH PRODUCT-ENTRY
AT END
DISPLAY "PRODUCT NOT FOUND"
WHEN PROD-CODE (PROD-INDEX) = WS-SEARCH-CODE
DISPLAY "FOUND PRODUCT: " PROD-NAME (PROD-INDEX)
DISPLAY "PRICE: $" PROD-PRICE (PROD-INDEX)
DISPLAY "IN STOCK: " PROD-QUANTITY (PROD-INDEX)
END-SEARCH.Using indexes for efficient table searching.
01 SORTED-EMPLOYEE-TABLE.
05 EMPLOYEE-ENTRY OCCURS 1000 TIMES
ASCENDING KEY IS EMP-ID
INDEXED BY EMP-INDEX.
10 EMP-ID PIC 9(6).
10 EMP-NAME PIC X(25).
10 EMP-DEPT PIC X(10).
10 EMP-SALARY PIC 9(6)V99.
PROCEDURE DIVISION.
BINARY-SEARCH-EMPLOYEE.
SEARCH ALL EMPLOYEE-ENTRY
AT END
DISPLAY "EMPLOYEE ID NOT FOUND: " WS-SEARCH-ID
WHEN EMP-ID (EMP-INDEX) = WS-SEARCH-ID
DISPLAY "EMPLOYEE FOUND:"
DISPLAY " ID: " EMP-ID (EMP-INDEX)
DISPLAY " NAME: " EMP-NAME (EMP-INDEX)
DISPLAY " DEPT: " EMP-DEPT (EMP-INDEX)
DISPLAY " SALARY: $" EMP-SALARY (EMP-INDEX)
END-SEARCH.
LOAD-EMPLOYEE-TABLE.
*> Load data in ascending order by EMP-ID
MOVE 100001 TO EMP-ID (1)
MOVE "ALICE JOHNSON" TO EMP-NAME (1)
MOVE "IT" TO EMP-DEPT (1)
MOVE 65000.00 TO EMP-SALARY (1)
MOVE 100002 TO EMP-ID (2)
MOVE "BOB SMITH" TO EMP-NAME (2)
MOVE "FINANCE" TO EMP-DEPT (2)
MOVE 58000.00 TO EMP-SALARY (2).Binary search on sorted tables using SEARCH ALL.
01 MONTHLY-TOTALS.
05 MONTH-DATA OCCURS 12 TIMES.
10 MONTH-NAME PIC X(9).
10 SALES-TOTAL PIC 9(8)V99.
10 TARGET-AMOUNT PIC 9(8)V99.
01 WS-MONTH-NAMES.
05 FILLER PIC X(108) VALUE
"JANUARY FEBRUARY MARCH APRIL MAY JUNE " &
"JULY AUGUST SEPTEMBEROCTOBER NOVEMBER DECEMBER ".
05 WS-MONTH-TABLE REDEFINES FILLER.
10 WS-MONTH-ENTRY OCCURS 12 TIMES PIC X(9).
PROCEDURE DIVISION.
INITIALIZE-MONTH-TABLE.
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > 12
MOVE WS-MONTH-ENTRY (WS-INDEX) TO MONTH-NAME (WS-INDEX)
MOVE ZERO TO SALES-TOTAL (WS-INDEX)
MOVE 100000.00 TO TARGET-AMOUNT (WS-INDEX)
END-PERFORM.
DISPLAY-MONTH-TABLE.
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > 12
DISPLAY WS-INDEX ". " MONTH-NAME (WS-INDEX)
" - SALES: $" SALES-TOTAL (WS-INDEX)
" TARGET: $" TARGET-AMOUNT (WS-INDEX)
END-PERFORM.Initializing tables with data and displaying contents.
01 SALES-REPORT-TABLE.
05 SALES-ENTRY OCCURS 100 TIMES.
10 SALESPERSON PIC X(20).
10 REGION PIC X(10).
10 SALES-AMOUNT PIC 9(8)V99.
10 COMMISSION PIC 9(6)V99.
01 WS-SORT-VARIABLES.
05 WS-INDEX PIC 999.
05 WS-INNER-INDEX PIC 999.
05 WS-ENTRY-COUNT PIC 999.
05 WS-TEMP-ENTRY.
10 WS-TEMP-PERSON PIC X(20).
10 WS-TEMP-REGION PIC X(10).
10 WS-TEMP-SALES PIC 9(8)V99.
10 WS-TEMP-COMM PIC 9(6)V99.
PROCEDURE DIVISION.
SORT-BY-SALES-AMOUNT.
*> Bubble sort by sales amount (descending)
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX >= WS-ENTRY-COUNT
PERFORM VARYING WS-INNER-INDEX FROM 1 BY 1
UNTIL WS-INNER-INDEX >= WS-ENTRY-COUNT
IF SALES-AMOUNT (WS-INNER-INDEX) <
SALES-AMOUNT (WS-INNER-INDEX + 1)
*> Swap entries
MOVE SALES-ENTRY (WS-INNER-INDEX) TO WS-TEMP-ENTRY
MOVE SALES-ENTRY (WS-INNER-INDEX + 1) TO
SALES-ENTRY (WS-INNER-INDEX)
MOVE WS-TEMP-ENTRY TO SALES-ENTRY (WS-INNER-INDEX + 1)
END-IF
END-PERFORM
END-PERFORM.
CALCULATE-COMMISSIONS.
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > WS-ENTRY-COUNT
COMPUTE COMMISSION (WS-INDEX) =
SALES-AMOUNT (WS-INDEX) * 0.05
END-PERFORM.
GENERATE-SALES-REPORT.
DISPLAY "SALES PERFORMANCE REPORT"
DISPLAY "========================"
DISPLAY "RANK SALESPERSON REGION SALES COMMISSION"
DISPLAY "---- ---------------- -------- --------- ---------"
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > WS-ENTRY-COUNT
DISPLAY WS-INDEX ". "
SALESPERSON (WS-INDEX) " "
REGION (WS-INDEX) " $"
SALES-AMOUNT (WS-INDEX) " $"
COMMISSION (WS-INDEX)
END-PERFORM.Sorting table data and generating reports.
01 COMPANY-STRUCTURE.
05 DEPARTMENT-COUNT PIC 99.
05 DEPARTMENT-DATA OCCURS 1 TO 20 TIMES
DEPENDING ON DEPARTMENT-COUNT
INDEXED BY DEPT-INDEX.
10 DEPT-NAME PIC X(20).
10 DEPT-BUDGET PIC 9(8)V99.
10 EMPLOYEE-COUNT PIC 999.
10 EMPLOYEE-DATA OCCURS 1 TO 50 TIMES
DEPENDING ON EMPLOYEE-COUNT
INDEXED BY EMP-INDEX.
15 EMP-NUM PIC 9(6).
15 EMP-NAME PIC X(25).
15 EMP-TITLE PIC X(20).
15 EMP-SALARY PIC 9(6)V99.
PROCEDURE DIVISION.
PROCESS-COMPANY-DATA.
PERFORM VARYING DEPT-INDEX FROM 1 BY 1
UNTIL DEPT-INDEX > DEPARTMENT-COUNT
DISPLAY "DEPARTMENT: " DEPT-NAME (DEPT-INDEX)
DISPLAY "BUDGET: $" DEPT-BUDGET (DEPT-INDEX)
DISPLAY "EMPLOYEES:"
PERFORM VARYING EMP-INDEX FROM 1 BY 1
UNTIL EMP-INDEX > EMPLOYEE-COUNT (DEPT-INDEX)
DISPLAY " " EMP-NUM (DEPT-INDEX, EMP-INDEX)
" - " EMP-NAME (DEPT-INDEX, EMP-INDEX)
" (" EMP-TITLE (DEPT-INDEX, EMP-INDEX) ")"
" $" EMP-SALARY (DEPT-INDEX, EMP-INDEX)
END-PERFORM
DISPLAY SPACES
END-PERFORM.Nested variable-length tables with complex processing.
01 STATISTICAL-DATA.
05 DATA-COUNT PIC 999.
05 DATA-VALUES OCCURS 1 TO 500 TIMES
DEPENDING ON DATA-COUNT.
10 VALUE-AMOUNT PIC S9(6)V99.
01 WS-STATISTICS.
05 WS-SUM PIC S9(10)V99.
05 WS-AVERAGE PIC S9(8)V99.
05 WS-MINIMUM PIC S9(6)V99.
05 WS-MAXIMUM PIC S9(6)V99.
05 WS-COUNT PIC 999.
05 WS-INDEX PIC 999.
PROCEDURE DIVISION.
CALCULATE-STATISTICS.
MOVE ZERO TO WS-SUM.
MOVE 999999.99 TO WS-MINIMUM.
MOVE -999999.99 TO WS-MAXIMUM.
PERFORM VARYING WS-INDEX FROM 1 BY 1
UNTIL WS-INDEX > DATA-COUNT
ADD VALUE-AMOUNT (WS-INDEX) TO WS-SUM
IF VALUE-AMOUNT (WS-INDEX) < WS-MINIMUM
MOVE VALUE-AMOUNT (WS-INDEX) TO WS-MINIMUM
END-IF
IF VALUE-AMOUNT (WS-INDEX) > WS-MAXIMUM
MOVE VALUE-AMOUNT (WS-INDEX) TO WS-MAXIMUM
END-IF
END-PERFORM.
COMPUTE WS-AVERAGE = WS-SUM / DATA-COUNT.
DISPLAY "STATISTICAL ANALYSIS:"
DISPLAY " COUNT: " DATA-COUNT
DISPLAY " SUM: $" WS-SUM
DISPLAY " AVERAGE: $" WS-AVERAGE
DISPLAY " MINIMUM: $" WS-MINIMUM
DISPLAY " MAXIMUM: $" WS-MAXIMUM.Statistical analysis of table data.
| Pattern | Use Case | Example |
|---|---|---|
| Fixed OCCURS | Known table size | OCCURS 12 TIMES |
| DEPENDING ON | Variable table size | OCCURS 1 TO 100 DEPENDING ON |
| INDEXED BY | Search operations | INDEXED BY TABLE-INDEX |
| KEY clause | Sorted tables | ASCENDING KEY IS DATA-FIELD |
Linear search through table elements
Binary search on sorted tables
Index manipulation and initialization
Loop control for table processing