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 5
Creating 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