Multi-way branching sends program control down exactly one path from many possibilities—department code A versus B versus C, years-of-service tiers, transaction type codes. IF handles two-way choice; long ELSE-IF ladders handle many but become unreadable and error-prone when ranges overlap or maintenance adds another code. CASE field-name structures dispatch: list WHEN value or WHEN low THRU high ranges, attach statements per branch, optional OTHERWISE for default, END-CASE closes. First match wins; later WHEN clauses never run for that evaluation. Control flow through CASE is flat within the block—no fall-through to next WHEN like some C switch unless statements complete and execution continues inside same WHEN body. This page teaches decision-table thinking, mapping business rules to WHEN ranges, OTHERWISE for safety, nesting CASE in IF, contrast with EQ THRU in IF, testing boundary values, and when CASE clarifies program flow versus PERFORM table-driven logic.
Business analysts often document rules as tables: when STATUS is 1 do X, when 2 do Y. CASE transcodes table rows into WHEN clauses. Each row becomes WHEN literal or range plus statements. OTHERWISE catches table default row. Reviewers compare CASE source to specification row by row—easier than hunting ELSE-IF scattered with duplicated field tests. Overlapping ranges cause first-match priority—document order when ranges touch at boundaries.
12345678910CASE DEPT-CODE WHEN 'PAY' PERFORM PAYROLL-ROUTING WHEN 'HR' PERFORM HR-ROUTING WHEN 'IT' PERFORM IT-ROUTING OTHERWISE PERFORM DEFAULT-ROUTING END-CASE
WHEN 0 THRU 4 assigns one path for inclusive range 0,1,2,3,4. Adjacent tiers use WHEN 5 THRU 9 without gap if 4 and 5 both covered—gap values fall through to OTHERWISE or skip block entirely. Boundary testing: values exactly on THRU endpoints must match spec. Numeric zoned fields compare as numeric; alphanumeric codes compare as character—type mismatch causes wrong branch silently.
| WHEN form | Matches | Control flow note |
|---|---|---|
| WHEN 5 | Exactly 5 | Single value dispatch |
| WHEN 1 THRU 3 | 1, 2, 3 inclusive | Tier band |
| WHEN A | Alphanumeric literal A | Quote character codes |
| OTHERWISE | All non-matching | Default path; prevents silent skip |
Two outcomes: IF suffices. Three to five related outcomes on same field: CASE often clearer. Ten plus outcomes: CASE strongly preferred. IF chains mixing different fields belong as nested IF or separate CASE blocks per driver field—not one CASE on field A with tests on field B inside WHEN bodies without restructuring. PERFORM per branch keeps CASE bodies thin; heavy logic in WHEN obscures dispatch table.
Execution after END-CASE continues sequentially regardless of which WHEN ran—CASE does not exit activity unless STOP, GOTO, or EXIT inside branch. Set output fields in each WHEN so downstream logic has consistent state. OTHERWISE should set error flag or default values when spec requires—avoid empty OTHERWISE that leaves prior iteration values in working storage.
Outer CASE on REGION, inner CASE on PRODUCT within each regional WHEN—tree of decisions. Nesting depth hurts readability beyond two levels; consider two-dimensional lookup table with PERFORM instead. Inner CASE must END-CASE before outer END-CASE. IF wraps CASE when precondition gates entire dispatch—IF RECORD-VALID EQ Y then CASE TYPE ...
DO WHILE loop body may CASE on line-type field per iteration—control flows per record type within batch stream. Avoid CASE inside tight inner loop on unchanged field—compute once before loop. Report BEFORE-LINE CASE on break-level field changes detail formatting path without GOTO spaghetti.
CASE is a mail sorter for one letter slot. You look at the zip code on the letter and put it in the right bin—WHEN zip is 100 THRU 199 goes here, WHEN 200 THRU 299 goes there. OTHERWISE is the junk drawer for letters that do not match any bin. You handle one letter at a time and only one bin wins.
1. CASE control flow selects path by:
2. First matching WHEN:
3. OTHERWISE provides:
4. CASE improves control flow over IF when:
5. CASE blocks end with: