Key Takeaways: Table Handling and Searching

  1. OCCURS defines tables at compile time. It can appear on levels 02-49, never on 01, 66, 77, or 88. Storage is allocated for the maximum number of entries.

  2. Indexes outperform subscripts because they store byte displacements rather than element numbers, eliminating runtime multiplication. Use INDEXED BY for heavily searched tables and manipulate indexes only with the SET statement.

  3. SEARCH performs serial (linear) search, starting at the current index position. You must SET the index to 1 before each search unless you intentionally start mid-table. Supports multiple WHEN clauses and complex conditions including OR.

  4. SEARCH ALL performs binary search in O(log n) time but requires: ASCENDING/DESCENDING KEY declared, data actually sorted, equality-only conditions, a single WHEN clause (AND is allowed, OR is not). Do not SET the index before SEARCH ALL.

  5. Multi-dimensional tables use nested OCCURS clauses (up to 7 levels). Calculate total memory carefully. Access elements with multiple subscripts/indexes separated by commas.

  6. OCCURS DEPENDING ON creates variable-length tables. The DEPENDING ON item must precede the OCCURS item. Always validate the DEPENDING ON value is within range before any table operation.

  7. Three loading strategies exist: hardcoded with REDEFINES (small, stable data), file-loaded (large or frequently changing data), and copybook-based (shared definitions across programs).

  8. Choose the right search strategy: Direct indexing for O(1) when keys map to positions. Serial search for small/unsorted tables or complex conditions. Binary search for large sorted tables with equality lookups.

  9. Defensive programming is non-negotiable: Validate boundaries, verify sort order, check for overflow during loading, confirm the table is loaded before searching, and always handle AT END conditions.

  10. Know the limits: When tables exceed ~100,000 entries or need dynamic updates, consider VSAM, DB2, or shared memory alternatives.