The INDEXED BY clause represents the foundational table index declaration mechanism within COBOL programming environments, providing automatic index creation and management capabilities that enable efficient table navigation, optimized array processing, and streamlined data structure access. This clause embodies advanced table handling principles by supporting multiple concurrent indexes, automatic index initialization, and enhanced performance characteristics while facilitating complex table operations, multi-dimensional array processing, and comprehensive data manipulation across enterprise applications requiring high-performance bulk data processing and optimal memory utilization patterns.
123456789101112131415161718192021222324252627282930313233343536373839404142434445*> Basic INDEXED BY syntax 01 table-name. 05 entry-name OCCURS n TIMES INDEXED BY index-name-1 [, index-name-2, ...]. *> Single index example 01 EMPLOYEE-TABLE. 05 EMP-RECORD OCCURS 100 TIMES INDEXED BY EMP-IDX. 10 EMP-ID PIC 9(6). 10 EMP-NAME PIC X(30). 10 EMP-SALARY PIC 9(7)V99. *> Multiple indexes for same table 01 SALES-DATA. 05 SALES-RECORD OCCURS 500 TIMES INDEXED BY MAIN-IDX, BACKUP-IDX, SEARCH-IDX. 10 SALE-DATE PIC 9(8). 10 SALE-AMOUNT PIC 9(8)V99. 10 CUSTOMER-ID PIC X(10). *> Multi-dimensional tables with indexes 01 MONTHLY-REPORT. 05 MONTH-DATA OCCURS 12 TIMES INDEXED BY MONTH-IDX. 10 MONTH-NAME PIC X(10). 10 DAILY-SALES OCCURS 31 TIMES INDEXED BY DAY-IDX. 15 SALES-AMT PIC 9(8)V99. 15 TRANS-CNT PIC 9(4). *> Complex nested structure with multiple indexes 01 COMPANY-STRUCTURE. 05 DIVISION OCCURS 5 TIMES INDEXED BY DIV-IDX. 10 DIV-NAME PIC X(20). 10 DEPARTMENT OCCURS 10 TIMES INDEXED BY DEPT-IDX. 15 DEPT-NAME PIC X(15). 15 EMPLOYEE OCCURS 50 TIMES INDEXED BY EMP-IDX. 20 EMP-DATA. 25 EMP-ID PIC 9(6). 25 EMP-NAME PIC X(25). 25 EMP-GRADE PIC 9(2).
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426IDENTIFICATION DIVISION. PROGRAM-ID. INDEXED-BY-DEMONSTRATION. DATA DIVISION. WORKING-STORAGE SECTION. 01 CUSTOMER-DATABASE. 05 CUSTOMER-RECORD OCCURS 2000 TIMES INDEXED BY CUST-IDX, READ-IDX, WRITE-IDX. 10 CUST-ID PIC X(10). 10 CUST-INFO. 15 CUST-NAME PIC X(40). 15 CUST-TYPE PIC X(10). 15 CREDIT-LIMIT PIC 9(8)V99. 15 BALANCE PIC S9(8)V99. 10 ADDRESS-INFO. 15 STREET PIC X(30). 15 CITY PIC X(20). 15 STATE PIC X(2). 15 ZIP-CODE PIC 9(5). 01 INVENTORY-SYSTEM. 05 CATEGORY OCCURS 20 TIMES INDEXED BY CAT-IDX. 10 CATEGORY-NAME PIC X(25). 10 PRODUCT OCCURS 100 TIMES INDEXED BY PROD-IDX, SORT-IDX. 15 PRODUCT-ID PIC X(15). 15 PRODUCT-NAME PIC X(40). 15 UNIT-PRICE PIC 9(6)V99. 15 QTY-ON-HAND PIC 9(6). 15 SUPPLIER OCCURS 5 TIMES INDEXED BY SUPP-IDX. 20 SUPP-ID PIC X(8). 20 SUPP-NAME PIC X(30). 20 COST PIC 9(6)V99. 01 TRANSACTION-LOG. 05 TRANS-ENTRY OCCURS 10000 TIMES INDEXED BY TRANS-IDX, PROCESS-IDX, ARCHIVE-IDX. 10 TRANS-HEADER. 15 TRANS-ID PIC X(12). 15 TRANS-DATE PIC 9(8). 15 TRANS-TIME PIC 9(6). 15 TRANS-TYPE PIC X(10). 10 TRANS-DETAILS. 15 CUSTOMER-ID PIC X(10). 15 AMOUNT PIC S9(8)V99. 15 DESCRIPTION PIC X(50). 10 TRANS-STATUS PIC X(10). 01 SALES-ANALYSIS. 05 YEAR-DATA OCCURS 5 TIMES INDEXED BY YEAR-IDX. 10 YEAR-NUMBER PIC 9(4). 10 QUARTER OCCURS 4 TIMES INDEXED BY QTR-IDX. 15 QTR-SALES PIC 9(10)V99. 15 MONTH OCCURS 3 TIMES INDEXED BY MONTH-IDX. 20 MONTH-SALES PIC 9(8)V99. 20 WEEK OCCURS 5 TIMES INDEXED BY WEEK-IDX. 25 WEEK-SALES PIC 9(6)V99. 25 DAY OCCURS 7 TIMES INDEXED BY DAY-IDX. 30 DAY-SALES PIC 9(5)V99. 01 WS-WORK-AREAS. 05 WS-CUSTOMER-COUNT PIC 9(4) VALUE 0. 05 WS-TOTAL-BALANCE PIC S9(10)V99 VALUE 0. 05 WS-SEARCH-KEY PIC X(10). 05 WS-FOUND-FLAG PIC X VALUE 'N'. 88 RECORD-FOUND VALUE 'Y'. 88 RECORD-NOT-FOUND VALUE 'N'. PROCEDURE DIVISION. MAIN-PROCESSING. PERFORM INITIALIZE-CUSTOMER-DATA PERFORM DEMONSTRATE-SINGLE-INDEX PERFORM DEMONSTRATE-MULTIPLE-INDEXES PERFORM DEMONSTRATE-NESTED-INDEXES PERFORM DEMONSTRATE-COMPLEX-PROCESSING PERFORM DEMONSTRATE-INDEX-COORDINATION STOP RUN. INITIALIZE-CUSTOMER-DATA. DISPLAY "=== INITIALIZING DATA WITH INDEXED TABLES ===" *> Initialize customer database using primary index PERFORM VARYING CUST-IDX FROM 1 BY 1 UNTIL CUST-IDX > 2000 STRING "CUST" CUST-IDX DELIMITED BY SIZE INTO CUST-ID(CUST-IDX) STRING "CUSTOMER " CUST-IDX " NAME" DELIMITED BY SIZE INTO CUST-NAME(CUST-IDX) *> Assign customer types cyclically EVALUATE FUNCTION MOD(CUST-IDX, 4) WHEN 0 MOVE "PLATINUM" TO CUST-TYPE(CUST-IDX) WHEN 1 MOVE "GOLD" TO CUST-TYPE(CUST-IDX) WHEN 2 MOVE "SILVER" TO CUST-TYPE(CUST-IDX) WHEN 3 MOVE "BRONZE" TO CUST-TYPE(CUST-IDX) END-EVALUATE *> Calculate credit limits based on type EVALUATE CUST-TYPE(CUST-IDX) WHEN "PLATINUM" COMPUTE CREDIT-LIMIT(CUST-IDX) = 100000.00 + (CUST-IDX * 10) WHEN "GOLD" COMPUTE CREDIT-LIMIT(CUST-IDX) = 50000.00 + (CUST-IDX * 5) WHEN "SILVER" COMPUTE CREDIT-LIMIT(CUST-IDX) = 25000.00 + (CUST-IDX * 3) WHEN "BRONZE" COMPUTE CREDIT-LIMIT(CUST-IDX) = 10000.00 + (CUST-IDX * 2) END-EVALUATE *> Generate balances COMPUTE BALANCE(CUST-IDX) = (FUNCTION MOD(CUST-IDX * 137, 50000)) - 10000 *> Generate addresses STRING "STREET " CUST-IDX DELIMITED BY SIZE INTO STREET(CUST-IDX) STRING "CITY" CUST-IDX DELIMITED BY SIZE INTO CITY(CUST-IDX) *> Cycle through states EVALUATE FUNCTION MOD(CUST-IDX, 5) WHEN 0 MOVE "NY" TO STATE(CUST-IDX) WHEN 1 MOVE "CA" TO STATE(CUST-IDX) WHEN 2 MOVE "TX" TO STATE(CUST-IDX) WHEN 3 MOVE "FL" TO STATE(CUST-IDX) WHEN 4 MOVE "IL" TO STATE(CUST-IDX) END-EVALUATE COMPUTE ZIP-CODE(CUST-IDX) = 10000 + FUNCTION MOD(CUST-IDX, 89999) END-PERFORM DISPLAY "Initialized " CUST-IDX " customer records" DISPLAY SPACES. DEMONSTRATE-SINGLE-INDEX. DISPLAY "=== SINGLE INDEX OPERATIONS ===" *> Basic index navigation SET CUST-IDX TO 1 DISPLAY "First customer: " CUST-NAME(CUST-IDX) DISPLAY "Type: " CUST-TYPE(CUST-IDX) DISPLAY "Balance: $" BALANCE(CUST-IDX) *> Jump to middle of table SET CUST-IDX TO 1000 DISPLAY "Middle customer: " CUST-NAME(CUST-IDX) DISPLAY "Credit Limit: $" CREDIT-LIMIT(CUST-IDX) *> Sequential processing with single index MOVE 0 TO WS-CUSTOMER-COUNT MOVE 0 TO WS-TOTAL-BALANCE PERFORM VARYING CUST-IDX FROM 1 BY 1 UNTIL CUST-IDX > 100 ADD 1 TO WS-CUSTOMER-COUNT ADD BALANCE(CUST-IDX) TO WS-TOTAL-BALANCE END-PERFORM DISPLAY "Processed " WS-CUSTOMER-COUNT " customers" DISPLAY "Total balance: $" WS-TOTAL-BALANCE DISPLAY SPACES. DEMONSTRATE-MULTIPLE-INDEXES. DISPLAY "=== MULTIPLE INDEX OPERATIONS ===" *> Use different indexes for different purposes *> READ-IDX for reading source data *> WRITE-IDX for writing filtered data SET READ-IDX TO 1 SET WRITE-IDX TO 1 *> Filter platinum customers to beginning of table PERFORM UNTIL READ-IDX > 2000 IF CUST-TYPE(READ-IDX) = "PLATINUM" *> Copy platinum customer to write position MOVE CUSTOMER-RECORD(READ-IDX) TO CUSTOMER-RECORD(WRITE-IDX) SET WRITE-IDX UP BY 1 END-IF SET READ-IDX UP BY 1 END-PERFORM SET WRITE-IDX DOWN BY 1 DISPLAY "Compacted " WRITE-IDX " platinum customers" *> Display first few platinum customers PERFORM VARYING CUST-IDX FROM 1 BY 1 UNTIL CUST-IDX > 10 DISPLAY "Platinum " CUST-IDX ": " CUST-NAME(CUST-IDX) END-PERFORM DISPLAY SPACES. DEMONSTRATE-NESTED-INDEXES. DISPLAY "=== NESTED INDEX OPERATIONS ===" *> Initialize inventory system with nested indexes PERFORM VARYING CAT-IDX FROM 1 BY 1 UNTIL CAT-IDX > 20 STRING "CATEGORY-" CAT-IDX DELIMITED BY SIZE INTO CATEGORY-NAME(CAT-IDX) *> Initialize products within each category PERFORM VARYING PROD-IDX FROM 1 BY 1 UNTIL PROD-IDX > 100 STRING "PROD-" CAT-IDX "-" PROD-IDX DELIMITED BY SIZE INTO PRODUCT-ID(CAT-IDX, PROD-IDX) STRING "PRODUCT " CAT-IDX "." PROD-IDX DELIMITED BY SIZE INTO PRODUCT-NAME(CAT-IDX, PROD-IDX) COMPUTE UNIT-PRICE(CAT-IDX, PROD-IDX) = (CAT-IDX * PROD-IDX * 1.50) + 10.00 COMPUTE QTY-ON-HAND(CAT-IDX, PROD-IDX) = FUNCTION MOD((CAT-IDX * PROD-IDX * 7), 1000) + 50 *> Initialize suppliers for each product PERFORM VARYING SUPP-IDX FROM 1 BY 1 UNTIL SUPP-IDX > 5 STRING "SUPP" SUPP-IDX DELIMITED BY SIZE INTO SUPP-ID(CAT-IDX, PROD-IDX, SUPP-IDX) STRING "SUPPLIER " CAT-IDX "." PROD-IDX "." SUPP-IDX DELIMITED BY SIZE INTO SUPP-NAME(CAT-IDX, PROD-IDX, SUPP-IDX) COMPUTE COST(CAT-IDX, PROD-IDX, SUPP-IDX) = UNIT-PRICE(CAT-IDX, PROD-IDX) * 0.60 END-PERFORM END-PERFORM END-PERFORM DISPLAY "Initialized inventory system:" DISPLAY "Categories: " CAT-IDX DISPLAY "Products per category: " PROD-IDX DISPLAY "Suppliers per product: " SUPP-IDX *> Sample nested access SET CAT-IDX TO 5 SET PROD-IDX TO 10 SET SUPP-IDX TO 2 DISPLAY "Sample product access:" DISPLAY "Category: " CATEGORY-NAME(CAT-IDX) DISPLAY "Product: " PRODUCT-NAME(CAT-IDX, PROD-IDX) DISPLAY "Supplier: " SUPP-NAME(CAT-IDX, PROD-IDX, SUPP-IDX) DISPLAY "Cost: $" COST(CAT-IDX, PROD-IDX, SUPP-IDX) DISPLAY SPACES. DEMONSTRATE-COMPLEX-PROCESSING. DISPLAY "=== COMPLEX MULTI-INDEX PROCESSING ===" *> Initialize transaction log PERFORM VARYING TRANS-IDX FROM 1 BY 1 UNTIL TRANS-IDX > 10000 STRING "TXN" TRANS-IDX DELIMITED BY SIZE INTO TRANS-ID(TRANS-IDX) COMPUTE TRANS-DATE(TRANS-IDX) = 20240101 + FUNCTION MOD(TRANS-IDX, 365) COMPUTE TRANS-TIME(TRANS-IDX) = FUNCTION MOD(TRANS-IDX * 137, 240000) EVALUATE FUNCTION MOD(TRANS-IDX, 4) WHEN 0 MOVE "PURCHASE" TO TRANS-TYPE(TRANS-IDX) WHEN 1 MOVE "PAYMENT" TO TRANS-TYPE(TRANS-IDX) WHEN 2 MOVE "REFUND" TO TRANS-TYPE(TRANS-IDX) WHEN 3 MOVE "ADJUSTMENT" TO TRANS-TYPE(TRANS-IDX) END-EVALUATE STRING "CUST" FUNCTION MOD(TRANS-IDX, 2000) + 1 DELIMITED BY SIZE INTO CUSTOMER-ID(TRANS-IDX) COMPUTE AMOUNT(TRANS-IDX) = (FUNCTION MOD(TRANS-IDX * 73, 100000)) / 100 MOVE "COMPLETED" TO TRANS-STATUS(TRANS-IDX) END-PERFORM *> Process transactions using multiple indexes SET TRANS-IDX TO 1 *> Read index SET PROCESS-IDX TO 1 *> Process index SET ARCHIVE-IDX TO 1 *> Archive index *> Separate transactions by type PERFORM UNTIL TRANS-IDX > 10000 EVALUATE TRANS-TYPE(TRANS-IDX) WHEN "PURCHASE" *> Process purchase transactions IF AMOUNT(TRANS-IDX) > 1000.00 MOVE TRANS-ENTRY(TRANS-IDX) TO TRANS-ENTRY(PROCESS-IDX) SET PROCESS-IDX UP BY 1 END-IF WHEN "PAYMENT" *> Archive payment transactions MOVE TRANS-ENTRY(TRANS-IDX) TO TRANS-ENTRY(ARCHIVE-IDX) SET ARCHIVE-IDX UP BY 1 END-EVALUATE SET TRANS-IDX UP BY 1 END-PERFORM SET PROCESS-IDX DOWN BY 1 SET ARCHIVE-IDX DOWN BY 1 DISPLAY "Transaction processing results:" DISPLAY "Large purchases identified: " PROCESS-IDX DISPLAY "Payments archived: " ARCHIVE-IDX DISPLAY SPACES. DEMONSTRATE-INDEX-COORDINATION. DISPLAY "=== INDEX COORDINATION PATTERNS ===" *> Initialize sales analysis with multi-dimensional indexes PERFORM VARYING YEAR-IDX FROM 1 BY 1 UNTIL YEAR-IDX > 5 COMPUTE YEAR-NUMBER(YEAR-IDX) = 2019 + YEAR-IDX PERFORM VARYING QTR-IDX FROM 1 BY 1 UNTIL QTR-IDX > 4 MOVE 0 TO QTR-SALES(YEAR-IDX, QTR-IDX) PERFORM VARYING MONTH-IDX FROM 1 BY 1 UNTIL MONTH-IDX > 3 COMPUTE MONTH-SALES(YEAR-IDX, QTR-IDX, MONTH-IDX) = (YEAR-IDX * QTR-IDX * MONTH-IDX * 10000) + 50000 ADD MONTH-SALES(YEAR-IDX, QTR-IDX, MONTH-IDX) TO QTR-SALES(YEAR-IDX, QTR-IDX) PERFORM VARYING WEEK-IDX FROM 1 BY 1 UNTIL WEEK-IDX > 5 COMPUTE WEEK-SALES(YEAR-IDX, QTR-IDX, MONTH-IDX, WEEK-IDX) = MONTH-SALES(YEAR-IDX, QTR-IDX, MONTH-IDX) / 5 PERFORM VARYING DAY-IDX FROM 1 BY 1 UNTIL DAY-IDX > 7 COMPUTE DAY-SALES(YEAR-IDX, QTR-IDX, MONTH-IDX, WEEK-IDX, DAY-IDX) = WEEK-SALES(YEAR-IDX, QTR-IDX, MONTH-IDX, WEEK-IDX) / 7 END-PERFORM END-PERFORM END-PERFORM END-PERFORM END-PERFORM *> Display coordinated analysis DISPLAY "Five-year sales analysis initialized" SET YEAR-IDX TO 3 SET QTR-IDX TO 2 DISPLAY "Sample data for " YEAR-NUMBER(YEAR-IDX) " Q" QTR-IDX ":" DISPLAY "Quarter total: $" QTR-SALES(YEAR-IDX, QTR-IDX) PERFORM VARYING MONTH-IDX FROM 1 BY 1 UNTIL MONTH-IDX > 3 DISPLAY " Month " MONTH-IDX ": $" MONTH-SALES(YEAR-IDX, QTR-IDX, MONTH-IDX) END-PERFORM DISPLAY SPACES. *> Advanced index manipulation routines SEARCH-CUSTOMER-BY-ID. *> Binary search using index (assumes sorted table) MOVE "CUST1000" TO WS-SEARCH-KEY SET RECORD-NOT-FOUND TO TRUE SET CUST-IDX TO 1 SET READ-IDX TO 2000 PERFORM UNTIL RECORD-FOUND OR CUST-IDX > READ-IDX SET WRITE-IDX TO CUST-IDX SET WRITE-IDX UP BY READ-IDX SET WRITE-IDX TO WRITE-IDX / 2 IF CUST-ID(WRITE-IDX) = WS-SEARCH-KEY SET RECORD-FOUND TO TRUE SET CUST-IDX TO WRITE-IDX ELSE IF CUST-ID(WRITE-IDX) < WS-SEARCH-KEY SET CUST-IDX TO WRITE-IDX SET CUST-IDX UP BY 1 ELSE SET READ-IDX TO WRITE-IDX SET READ-IDX DOWN BY 1 END-IF END-IF END-PERFORM IF RECORD-FOUND DISPLAY "Found customer: " CUST-NAME(CUST-IDX) ELSE DISPLAY "Customer not found: " WS-SEARCH-KEY END-IF. PARALLEL-TABLE-PROCESSING. *> Process two tables in parallel using separate indexes SET CUST-IDX TO 1 SET TRANS-IDX TO 1 PERFORM UNTIL CUST-IDX > 100 OR TRANS-IDX > 100 *> Process customer and corresponding transaction DISPLAY "Processing customer " CUST-IDX " and transaction " TRANS-IDX SET CUST-IDX UP BY 1 SET TRANS-IDX UP BY 1 END-PERFORM. TABLE-COMPRESSION. *> Compress table by removing empty entries SET READ-IDX TO 1 SET WRITE-IDX TO 1 PERFORM UNTIL READ-IDX > 2000 IF CUST-ID(READ-IDX) NOT = SPACES IF READ-IDX NOT = WRITE-IDX MOVE CUSTOMER-RECORD(READ-IDX) TO CUSTOMER-RECORD(WRITE-IDX) END-IF SET WRITE-IDX UP BY 1 END-IF SET READ-IDX UP BY 1 END-PERFORM SET WRITE-IDX DOWN BY 1 DISPLAY "Compressed table to " WRITE-IDX " active records".
What does the INDEXED BY clause automatically create?
Answer: The INDEXED BY clause automatically creates index data items that can be used to navigate table elements efficiently. These indexes don't need to be explicitly declared in the Data Division.
Why would you define multiple indexes for the same table?
Answer: Multiple indexes allow different parts of your program to navigate the same table independently, enabling operations like reading with one index while writing with another, or maintaining separate search positions.