MainframeMaster

COBOL Tutorial

COBOL ALTERNATE Clause

The ALTERNATE clause represents one of COBOL's most sophisticated and powerful file organization mechanisms, serving as the primary tool for defining alternate keys in indexed files that enable multiple access paths to the same data records. Far more than a simple file access method, the ALTERNATE clause embodies COBOL's comprehensive approach to data organization by providing secondary indexing capabilities, multiple sort sequences, flexible data retrieval patterns, and advanced file navigation techniques that enable applications to access the same data through different logical views while maintaining data integrity, performance optimization, and sophisticated query capabilities that are essential for complex business applications requiring multiple data access patterns and comprehensive information retrieval systems.

In enterprise computing environments, the ALTERNATE clause serves as a critical foundation for advanced database-like functionality within COBOL file systems, enabling developers to create sophisticated data access applications that support multiple search criteria, implement complex reporting requirements, provide flexible data navigation, and maintain high-performance data retrieval capabilities. Its capabilities extend far beyond simple sequential access to encompass sophisticated indexing strategies, duplicate key handling, partial key searches, and integration with modern database concepts that are essential for applications requiring comprehensive data access flexibility and enterprise-grade file management capabilities that support complex business data organization requirements and advanced information retrieval patterns.

ALTERNATE Clause Fundamentals

Basic ALTERNATE Key Definition

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
*> Basic ALTERNATE key definition in SELECT statement SELECT CUSTOMER-FILE ASSIGN TO "CUSTOMER.DAT" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS CUSTOMER-ID ALTERNATE RECORD KEY IS CUSTOMER-NAME ALTERNATE RECORD KEY IS CUSTOMER-ZIP-CODE ALTERNATE RECORD KEY IS CUSTOMER-PHONE FILE STATUS IS CUSTOMER-FILE-STATUS. *> File record structure FD CUSTOMER-FILE. 01 CUSTOMER-RECORD. 05 CUSTOMER-ID PIC X(10). 05 CUSTOMER-NAME PIC X(30). 05 CUSTOMER-ADDRESS PIC X(50). 05 CUSTOMER-CITY PIC X(20). 05 CUSTOMER-STATE PIC X(2). 05 CUSTOMER-ZIP-CODE PIC X(10). 05 CUSTOMER-PHONE PIC X(15). 05 CUSTOMER-EMAIL PIC X(40). 05 CUSTOMER-STATUS PIC X(10). *> Working storage for key fields 01 WS-SEARCH-KEYS. 05 WS-SEARCH-NAME PIC X(30). 05 WS-SEARCH-ZIP PIC X(10). 05 WS-SEARCH-PHONE PIC X(15).

Basic ALTERNATE key definitions create secondary access paths to indexed file data.

ALTERNATE Keys with Duplicates

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
*> ALTERNATE keys allowing duplicate values SELECT EMPLOYEE-FILE ASSIGN TO "EMPLOYEE.DAT" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS EMPLOYEE-ID ALTERNATE RECORD KEY IS DEPARTMENT-CODE WITH DUPLICATES ALTERNATE RECORD KEY IS SALARY-GRADE WITH DUPLICATES ALTERNATE RECORD KEY IS HIRE-DATE WITH DUPLICATES ALTERNATE RECORD KEY IS LAST-NAME WITH DUPLICATES FILE STATUS IS EMPLOYEE-FILE-STATUS. *> Employee record structure FD EMPLOYEE-FILE. 01 EMPLOYEE-RECORD. 05 EMPLOYEE-ID PIC X(8). 05 FIRST-NAME PIC X(20). 05 LAST-NAME PIC X(25). 05 DEPARTMENT-CODE PIC X(5). 05 SALARY-GRADE PIC X(3). 05 HIRE-DATE PIC X(8). 05 SALARY-AMOUNT PIC 9(7)V99. 05 MANAGER-ID PIC X(8). 05 EMPLOYEE-STATUS PIC X(10). *> Search criteria for duplicate keys 01 WS-DEPARTMENT-SEARCH. 05 WS-DEPT-CODE PIC X(5). 05 WS-DEPT-COUNTER PIC 9(5) VALUE 0. 01 WS-SALARY-SEARCH. 05 WS-SALARY-GRADE PIC X(3). 05 WS-SALARY-COUNTER PIC 9(5) VALUE 0.

WITH DUPLICATES clause allows multiple records with the same alternate key value.

Complex ALTERNATE Key Structures

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
*> Complex ALTERNATE keys with compound fields SELECT INVENTORY-FILE ASSIGN TO "INVENTORY.DAT" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS ITEM-ID ALTERNATE RECORD KEY IS CATEGORY-SUBCATEGORY-KEY = ITEM-CATEGORY, ITEM-SUBCATEGORY ALTERNATE RECORD KEY IS SUPPLIER-ITEM-KEY = SUPPLIER-CODE, ITEM-NUMBER WITH DUPLICATES ALTERNATE RECORD KEY IS LOCATION-STATUS-KEY = WAREHOUSE-LOCATION, ITEM-STATUS ALTERNATE RECORD KEY IS PRICE-RANGE-KEY = PRICE-CATEGORY, ITEM-PRIORITY WITH DUPLICATES FILE STATUS IS INVENTORY-FILE-STATUS. *> Inventory record with compound key fields FD INVENTORY-FILE. 01 INVENTORY-RECORD. 05 ITEM-ID PIC X(12). 05 ITEM-NUMBER PIC X(15). 05 ITEM-DESCRIPTION PIC X(50). 05 ITEM-CATEGORY PIC X(10). 05 ITEM-SUBCATEGORY PIC X(10). 05 SUPPLIER-CODE PIC X(8). 05 WAREHOUSE-LOCATION PIC X(6). 05 ITEM-STATUS PIC X(10). 05 PRICE-CATEGORY PIC X(5). 05 ITEM-PRIORITY PIC X(3). 05 UNIT-PRICE PIC 9(6)V99. 05 QUANTITY-ON-HAND PIC 9(8). 05 REORDER-LEVEL PIC 9(6). *> Compound key search structures 01 WS-COMPOUND-KEYS. 05 WS-CATEGORY-SUBCATEGORY-KEY. 10 WS-SEARCH-CATEGORY PIC X(10). 10 WS-SEARCH-SUBCATEGORY PIC X(10). 05 WS-SUPPLIER-ITEM-KEY. 10 WS-SEARCH-SUPPLIER PIC X(8). 10 WS-SEARCH-ITEM-NUM PIC X(15). 05 WS-LOCATION-STATUS-KEY. 10 WS-SEARCH-LOCATION PIC X(6). 10 WS-SEARCH-STATUS PIC X(10).

Compound ALTERNATE keys combine multiple fields for sophisticated data organization.

Comprehensive Example

cobol
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
IDENTIFICATION DIVISION. PROGRAM-ID. ALTERNATE-KEY-DEMO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. *> Customer master file with multiple alternate keys SELECT CUSTOMER-MASTER-FILE ASSIGN TO "CUSTMAST.DAT" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS CUSTOMER-ID ALTERNATE RECORD KEY IS CUSTOMER-NAME WITH DUPLICATES ALTERNATE RECORD KEY IS CUSTOMER-ZIP-CODE WITH DUPLICATES ALTERNATE RECORD KEY IS CUSTOMER-PHONE ALTERNATE RECORD KEY IS CUSTOMER-EMAIL ALTERNATE RECORD KEY IS ACCOUNT-STATUS-KEY = ACCOUNT-STATUS, CREDIT-RATING WITH DUPLICATES FILE STATUS IS CUSTOMER-FILE-STATUS. *> Transaction file with alternate keys SELECT TRANSACTION-FILE ASSIGN TO "TRANS.DAT" ORGANIZATION IS INDEXED ACCESS MODE IS DYNAMIC RECORD KEY IS TRANSACTION-ID ALTERNATE RECORD KEY IS CUSTOMER-TRANS-KEY = CUSTOMER-ID, TRANSACTION-DATE WITH DUPLICATES ALTERNATE RECORD KEY IS DATE-TYPE-KEY = TRANSACTION-DATE, TRANSACTION-TYPE WITH DUPLICATES ALTERNATE RECORD KEY IS AMOUNT-RANGE-KEY = AMOUNT-CATEGORY, TRANSACTION-STATUS WITH DUPLICATES FILE STATUS IS TRANSACTION-FILE-STATUS. DATA DIVISION. FILE SECTION. FD CUSTOMER-MASTER-FILE. 01 CUSTOMER-MASTER-RECORD. 05 CUSTOMER-ID PIC X(10). 05 CUSTOMER-NAME PIC X(30). 05 CUSTOMER-ADDRESS PIC X(50). 05 CUSTOMER-CITY PIC X(20). 05 CUSTOMER-STATE PIC X(2). 05 CUSTOMER-ZIP-CODE PIC X(10). 05 CUSTOMER-PHONE PIC X(15). 05 CUSTOMER-EMAIL PIC X(40). 05 ACCOUNT-STATUS PIC X(10). 05 CREDIT-RATING PIC X(5). 05 ACCOUNT-BALANCE PIC S9(8)V99. 05 LAST-ACTIVITY-DATE PIC X(8). FD TRANSACTION-FILE. 01 TRANSACTION-RECORD. 05 TRANSACTION-ID PIC X(15). 05 CUSTOMER-ID PIC X(10). 05 TRANSACTION-DATE PIC X(8). 05 TRANSACTION-TYPE PIC X(10). 05 TRANSACTION-AMOUNT PIC S9(8)V99. 05 AMOUNT-CATEGORY PIC X(5). 05 TRANSACTION-STATUS PIC X(10). 05 DESCRIPTION PIC X(50). 05 REFERENCE-NUMBER PIC X(20). WORKING-STORAGE SECTION. *> File status variables 01 CUSTOMER-FILE-STATUS PIC X(2). 88 CUSTOMER-FILE-OK VALUE "00". 88 CUSTOMER-EOF VALUE "10". 88 CUSTOMER-NOT-FOUND VALUE "23". 01 TRANSACTION-FILE-STATUS PIC X(2). 88 TRANSACTION-FILE-OK VALUE "00". 88 TRANSACTION-EOF VALUE "10". 88 TRANSACTION-NOT-FOUND VALUE "23". *> Search key structures 01 WS-SEARCH-CRITERIA. 05 WS-SEARCH-NAME PIC X(30). 05 WS-SEARCH-ZIP PIC X(10). 05 WS-SEARCH-PHONE PIC X(15). 05 WS-SEARCH-EMAIL PIC X(40). 05 WS-SEARCH-STATUS PIC X(10). 05 WS-SEARCH-RATING PIC X(5). *> Compound key search structures 01 WS-COMPOUND-SEARCH-KEYS. 05 WS-ACCOUNT-STATUS-KEY. 10 WS-STATUS-SEARCH PIC X(10). 10 WS-RATING-SEARCH PIC X(5). 05 WS-CUSTOMER-TRANS-KEY. 10 WS-CUST-ID-SEARCH PIC X(10). 10 WS-TRANS-DATE-SEARCH PIC X(8). 05 WS-DATE-TYPE-KEY. 10 WS-DATE-SEARCH PIC X(8). 10 WS-TYPE-SEARCH PIC X(10). 05 WS-AMOUNT-RANGE-KEY. 10 WS-AMOUNT-CAT-SEARCH PIC X(5). 10 WS-TRANS-STATUS-SEARCH PIC X(10). *> Processing counters and flags 01 WS-PROCESSING-COUNTERS. 05 WS-RECORDS-READ PIC 9(7) VALUE 0. 05 WS-RECORDS-FOUND PIC 9(7) VALUE 0. 05 WS-DUPLICATE-COUNT PIC 9(5) VALUE 0. 05 WS-SEARCH-COUNT PIC 9(5) VALUE 0. *> Display and formatting variables 01 WS-DISPLAY-FIELDS. 05 WS-FORMATTED-AMOUNT PIC $$$,$$$,$$9.99. 05 WS-FORMATTED-DATE PIC X(2)/X(2)/X(4). 05 WS-FORMATTED-PHONE PIC X(3)-X(3)-X(4). *> Menu and control variables 01 WS-MENU-CONTROL. 05 WS-MENU-CHOICE PIC X(1). 05 WS-CONTINUE-FLAG PIC X(1) VALUE "Y". 88 CONTINUE-PROCESSING VALUE "Y". 88 STOP-PROCESSING VALUE "N". PROCEDURE DIVISION. MAIN-PROCESSING. DISPLAY "=== ALTERNATE Key Demonstration ===". DISPLAY " ". PERFORM OPEN-FILES PERFORM DEMONSTRATE-ALTERNATE-KEY-USAGE PERFORM CLOSE-FILES DISPLAY " ". DISPLAY "ALTERNATE key demonstration completed successfully". STOP RUN. OPEN-FILES. OPEN I-O CUSTOMER-MASTER-FILE. IF NOT CUSTOMER-FILE-OK DISPLAY "Error opening customer file: " CUSTOMER-FILE-STATUS STOP RUN END-IF. OPEN I-O TRANSACTION-FILE. IF NOT TRANSACTION-FILE-OK DISPLAY "Error opening transaction file: " TRANSACTION-FILE-STATUS STOP RUN END-IF. DEMONSTRATE-ALTERNATE-KEY-USAGE. PERFORM UNTIL STOP-PROCESSING PERFORM DISPLAY-MENU PERFORM GET-MENU-CHOICE PERFORM PROCESS-MENU-CHOICE END-PERFORM. DISPLAY-MENU. DISPLAY " ". DISPLAY "ALTERNATE Key Search Options:". DISPLAY "=============================". DISPLAY "1. Search by Customer Name". DISPLAY "2. Search by ZIP Code". DISPLAY "3. Search by Phone Number". DISPLAY "4. Search by Email Address". DISPLAY "5. Search by Account Status and Credit Rating". DISPLAY "6. Search Transactions by Customer and Date". DISPLAY "7. Search Transactions by Date and Type". DISPLAY "8. Search Transactions by Amount Category". DISPLAY "9. Demonstrate Duplicate Key Processing". DISPLAY "0. Exit". DISPLAY " ". GET-MENU-CHOICE. DISPLAY "Enter your choice (0-9): " WITH NO ADVANCING. ACCEPT WS-MENU-CHOICE. PROCESS-MENU-CHOICE. EVALUATE WS-MENU-CHOICE WHEN "1" PERFORM SEARCH-BY-CUSTOMER-NAME WHEN "2" PERFORM SEARCH-BY-ZIP-CODE WHEN "3" PERFORM SEARCH-BY-PHONE WHEN "4" PERFORM SEARCH-BY-EMAIL WHEN "5" PERFORM SEARCH-BY-STATUS-RATING WHEN "6" PERFORM SEARCH-TRANSACTIONS-BY-CUSTOMER-DATE WHEN "7" PERFORM SEARCH-TRANSACTIONS-BY-DATE-TYPE WHEN "8" PERFORM SEARCH-TRANSACTIONS-BY-AMOUNT-CATEGORY WHEN "9" PERFORM DEMONSTRATE-DUPLICATE-PROCESSING WHEN "0" SET STOP-PROCESSING TO TRUE WHEN OTHER DISPLAY "Invalid choice. Please try again." END-EVALUATE. SEARCH-BY-CUSTOMER-NAME. DISPLAY " ". DISPLAY "Search by Customer Name:". DISPLAY "========================". DISPLAY "Enter customer name: " WITH NO ADVANCING. ACCEPT WS-SEARCH-NAME. MOVE WS-SEARCH-NAME TO CUSTOMER-NAME. START CUSTOMER-MASTER-FILE KEY IS EQUAL TO CUSTOMER-NAME INVALID KEY DISPLAY "No customer found with name: " WS-SEARCH-NAME NOT INVALID KEY PERFORM READ-AND-DISPLAY-CUSTOMER END-START. SEARCH-BY-ZIP-CODE. DISPLAY " ". DISPLAY "Search by ZIP Code:". DISPLAY "===================". DISPLAY "Enter ZIP code: " WITH NO ADVANCING. ACCEPT WS-SEARCH-ZIP. MOVE WS-SEARCH-ZIP TO CUSTOMER-ZIP-CODE. START CUSTOMER-MASTER-FILE KEY IS EQUAL TO CUSTOMER-ZIP-CODE INVALID KEY DISPLAY "No customers found in ZIP code: " WS-SEARCH-ZIP NOT INVALID KEY PERFORM READ-ALL-CUSTOMERS-IN-ZIP END-START. SEARCH-BY-PHONE. DISPLAY " ". DISPLAY "Search by Phone Number:". DISPLAY "=======================". DISPLAY "Enter phone number: " WITH NO ADVANCING. ACCEPT WS-SEARCH-PHONE. MOVE WS-SEARCH-PHONE TO CUSTOMER-PHONE. START CUSTOMER-MASTER-FILE KEY IS EQUAL TO CUSTOMER-PHONE INVALID KEY DISPLAY "No customer found with phone: " WS-SEARCH-PHONE NOT INVALID KEY PERFORM READ-AND-DISPLAY-CUSTOMER END-START. SEARCH-BY-EMAIL. DISPLAY " ". DISPLAY "Search by Email Address:". DISPLAY "========================". DISPLAY "Enter email address: " WITH NO ADVANCING. ACCEPT WS-SEARCH-EMAIL. MOVE WS-SEARCH-EMAIL TO CUSTOMER-EMAIL. START CUSTOMER-MASTER-FILE KEY IS EQUAL TO CUSTOMER-EMAIL INVALID KEY DISPLAY "No customer found with email: " WS-SEARCH-EMAIL NOT INVALID KEY PERFORM READ-AND-DISPLAY-CUSTOMER END-START. SEARCH-BY-STATUS-RATING. DISPLAY " ". DISPLAY "Search by Account Status and Credit Rating:". DISPLAY "===========================================". DISPLAY "Enter account status: " WITH NO ADVANCING. ACCEPT WS-STATUS-SEARCH. DISPLAY "Enter credit rating: " WITH NO ADVANCING. ACCEPT WS-RATING-SEARCH. MOVE WS-STATUS-SEARCH TO ACCOUNT-STATUS. MOVE WS-RATING-SEARCH TO CREDIT-RATING. START CUSTOMER-MASTER-FILE KEY IS EQUAL TO ACCOUNT-STATUS-KEY INVALID KEY DISPLAY "No customers found with status: " WS-STATUS-SEARCH " and rating: " WS-RATING-SEARCH NOT INVALID KEY PERFORM READ-ALL-CUSTOMERS-BY-STATUS-RATING END-START. SEARCH-TRANSACTIONS-BY-CUSTOMER-DATE. DISPLAY " ". DISPLAY "Search Transactions by Customer and Date:". DISPLAY "=========================================". DISPLAY "Enter customer ID: " WITH NO ADVANCING. ACCEPT WS-CUST-ID-SEARCH. DISPLAY "Enter transaction date (YYYYMMDD): " WITH NO ADVANCING. ACCEPT WS-TRANS-DATE-SEARCH. MOVE WS-CUST-ID-SEARCH TO CUSTOMER-ID OF TRANSACTION-RECORD. MOVE WS-TRANS-DATE-SEARCH TO TRANSACTION-DATE. START TRANSACTION-FILE KEY IS EQUAL TO CUSTOMER-TRANS-KEY INVALID KEY DISPLAY "No transactions found for customer: " WS-CUST-ID-SEARCH " on date: " WS-TRANS-DATE-SEARCH NOT INVALID KEY PERFORM READ-ALL-CUSTOMER-TRANSACTIONS END-START. SEARCH-TRANSACTIONS-BY-DATE-TYPE. DISPLAY " ". DISPLAY "Search Transactions by Date and Type:". DISPLAY "=====================================". DISPLAY "Enter transaction date (YYYYMMDD): " WITH NO ADVANCING. ACCEPT WS-DATE-SEARCH. DISPLAY "Enter transaction type: " WITH NO ADVANCING. ACCEPT WS-TYPE-SEARCH. MOVE WS-DATE-SEARCH TO TRANSACTION-DATE. MOVE WS-TYPE-SEARCH TO TRANSACTION-TYPE. START TRANSACTION-FILE KEY IS EQUAL TO DATE-TYPE-KEY INVALID KEY DISPLAY "No transactions found for date: " WS-DATE-SEARCH " and type: " WS-TYPE-SEARCH NOT INVALID KEY PERFORM READ-ALL-DATE-TYPE-TRANSACTIONS END-START. SEARCH-TRANSACTIONS-BY-AMOUNT-CATEGORY. DISPLAY " ". DISPLAY "Search Transactions by Amount Category:". DISPLAY "=======================================". DISPLAY "Enter amount category: " WITH NO ADVANCING. ACCEPT WS-AMOUNT-CAT-SEARCH. DISPLAY "Enter transaction status: " WITH NO ADVANCING. ACCEPT WS-TRANS-STATUS-SEARCH. MOVE WS-AMOUNT-CAT-SEARCH TO AMOUNT-CATEGORY. MOVE WS-TRANS-STATUS-SEARCH TO TRANSACTION-STATUS. START TRANSACTION-FILE KEY IS EQUAL TO AMOUNT-RANGE-KEY INVALID KEY DISPLAY "No transactions found for category: " WS-AMOUNT-CAT-SEARCH " and status: " WS-TRANS-STATUS-SEARCH NOT INVALID KEY PERFORM READ-ALL-AMOUNT-CATEGORY-TRANSACTIONS END-START. READ-AND-DISPLAY-CUSTOMER. READ CUSTOMER-MASTER-FILE NEXT RECORD. IF CUSTOMER-FILE-OK PERFORM DISPLAY-CUSTOMER-DETAILS ADD 1 TO WS-RECORDS-FOUND ELSE DISPLAY "Error reading customer record: " CUSTOMER-FILE-STATUS END-IF. READ-ALL-CUSTOMERS-IN-ZIP. MOVE 0 TO WS-DUPLICATE-COUNT. PERFORM UNTIL NOT CUSTOMER-FILE-OK OR CUSTOMER-EOF READ CUSTOMER-MASTER-FILE NEXT RECORD IF CUSTOMER-FILE-OK IF CUSTOMER-ZIP-CODE = WS-SEARCH-ZIP ADD 1 TO WS-DUPLICATE-COUNT PERFORM DISPLAY-CUSTOMER-SUMMARY ELSE SET CUSTOMER-EOF TO TRUE END-IF END-IF END-PERFORM. DISPLAY "Total customers found in ZIP " WS-SEARCH-ZIP ": " WS-DUPLICATE-COUNT. READ-ALL-CUSTOMERS-BY-STATUS-RATING. MOVE 0 TO WS-DUPLICATE-COUNT. PERFORM UNTIL NOT CUSTOMER-FILE-OK OR CUSTOMER-EOF READ CUSTOMER-MASTER-FILE NEXT RECORD IF CUSTOMER-FILE-OK IF ACCOUNT-STATUS = WS-STATUS-SEARCH AND CREDIT-RATING = WS-RATING-SEARCH ADD 1 TO WS-DUPLICATE-COUNT PERFORM DISPLAY-CUSTOMER-SUMMARY ELSE SET CUSTOMER-EOF TO TRUE END-IF END-IF END-PERFORM. DISPLAY "Total customers found with status " WS-STATUS-SEARCH " and rating " WS-RATING-SEARCH ": " WS-DUPLICATE-COUNT. READ-ALL-CUSTOMER-TRANSACTIONS. MOVE 0 TO WS-DUPLICATE-COUNT. PERFORM UNTIL NOT TRANSACTION-FILE-OK OR TRANSACTION-EOF READ TRANSACTION-FILE NEXT RECORD IF TRANSACTION-FILE-OK IF CUSTOMER-ID OF TRANSACTION-RECORD = WS-CUST-ID-SEARCH AND TRANSACTION-DATE = WS-TRANS-DATE-SEARCH ADD 1 TO WS-DUPLICATE-COUNT PERFORM DISPLAY-TRANSACTION-SUMMARY ELSE SET TRANSACTION-EOF TO TRUE END-IF END-IF END-PERFORM. DISPLAY "Total transactions found: " WS-DUPLICATE-COUNT. READ-ALL-DATE-TYPE-TRANSACTIONS. MOVE 0 TO WS-DUPLICATE-COUNT. PERFORM UNTIL NOT TRANSACTION-FILE-OK OR TRANSACTION-EOF READ TRANSACTION-FILE NEXT RECORD IF TRANSACTION-FILE-OK IF TRANSACTION-DATE = WS-DATE-SEARCH AND TRANSACTION-TYPE = WS-TYPE-SEARCH ADD 1 TO WS-DUPLICATE-COUNT PERFORM DISPLAY-TRANSACTION-SUMMARY ELSE SET TRANSACTION-EOF TO TRUE END-IF END-IF END-PERFORM. DISPLAY "Total transactions found: " WS-DUPLICATE-COUNT. READ-ALL-AMOUNT-CATEGORY-TRANSACTIONS. MOVE 0 TO WS-DUPLICATE-COUNT. PERFORM UNTIL NOT TRANSACTION-FILE-OK OR TRANSACTION-EOF READ TRANSACTION-FILE NEXT RECORD IF TRANSACTION-FILE-OK IF AMOUNT-CATEGORY = WS-AMOUNT-CAT-SEARCH AND TRANSACTION-STATUS = WS-TRANS-STATUS-SEARCH ADD 1 TO WS-DUPLICATE-COUNT PERFORM DISPLAY-TRANSACTION-SUMMARY ELSE SET TRANSACTION-EOF TO TRUE END-IF END-IF END-PERFORM. DISPLAY "Total transactions found: " WS-DUPLICATE-COUNT. DISPLAY-CUSTOMER-DETAILS. DISPLAY " ". DISPLAY "Customer Details:". DISPLAY "================". DISPLAY "Customer ID: " CUSTOMER-ID. DISPLAY "Name: " CUSTOMER-NAME. DISPLAY "Address: " CUSTOMER-ADDRESS. DISPLAY "City: " CUSTOMER-CITY ", " CUSTOMER-STATE " " CUSTOMER-ZIP-CODE. MOVE CUSTOMER-PHONE TO WS-FORMATTED-PHONE. DISPLAY "Phone: " WS-FORMATTED-PHONE. DISPLAY "Email: " CUSTOMER-EMAIL. DISPLAY "Account Status: " ACCOUNT-STATUS. DISPLAY "Credit Rating: " CREDIT-RATING. MOVE ACCOUNT-BALANCE TO WS-FORMATTED-AMOUNT. DISPLAY "Account Balance: " WS-FORMATTED-AMOUNT. MOVE LAST-ACTIVITY-DATE TO WS-FORMATTED-DATE. DISPLAY "Last Activity: " WS-FORMATTED-DATE. DISPLAY-CUSTOMER-SUMMARY. DISPLAY CUSTOMER-ID " - " CUSTOMER-NAME " - " CUSTOMER-ZIP-CODE. DISPLAY-TRANSACTION-SUMMARY. MOVE TRANSACTION-AMOUNT TO WS-FORMATTED-AMOUNT. DISPLAY TRANSACTION-ID " - " TRANSACTION-TYPE " - " WS-FORMATTED-AMOUNT. DEMONSTRATE-DUPLICATE-PROCESSING. DISPLAY " ". DISPLAY "Duplicate Key Processing Demonstration:". DISPLAY "======================================". DISPLAY "Processing all customers by ZIP code...". MOVE SPACES TO CUSTOMER-ZIP-CODE. START CUSTOMER-MASTER-FILE KEY IS GREATER THAN CUSTOMER-ZIP-CODE INVALID KEY DISPLAY "No customers found" NOT INVALID KEY PERFORM PROCESS-ALL-ZIP-CODES END-START. PROCESS-ALL-ZIP-CODES. MOVE SPACES TO WS-SEARCH-ZIP. MOVE 0 TO WS-SEARCH-COUNT. PERFORM UNTIL CUSTOMER-EOF READ CUSTOMER-MASTER-FILE NEXT RECORD IF CUSTOMER-FILE-OK IF CUSTOMER-ZIP-CODE NOT = WS-SEARCH-ZIP IF WS-SEARCH-COUNT > 0 DISPLAY "ZIP " WS-SEARCH-ZIP ": " WS-SEARCH-COUNT " customers" END-IF MOVE CUSTOMER-ZIP-CODE TO WS-SEARCH-ZIP MOVE 1 TO WS-SEARCH-COUNT ELSE ADD 1 TO WS-SEARCH-COUNT END-IF END-IF END-PERFORM. IF WS-SEARCH-COUNT > 0 DISPLAY "ZIP " WS-SEARCH-ZIP ": " WS-SEARCH-COUNT " customers" END-IF. CLOSE-FILES. CLOSE CUSTOMER-MASTER-FILE. CLOSE TRANSACTION-FILE.

Best Practices and Guidelines

Recommended Practices

  • Design ALTERNATE keys based on actual query requirements
  • Use WITH DUPLICATES when multiple records may share key values
  • Create compound keys for complex search criteria
  • Consider performance impact of multiple alternate keys
  • Document all alternate key purposes and usage patterns
  • Test alternate key performance with realistic data volumes
  • Use meaningful field combinations for compound keys
  • Plan for future query requirements when designing keys

Common Pitfalls

  • Creating too many alternate keys affecting performance
  • Not using WITH DUPLICATES when needed
  • Poor compound key field ordering
  • Not handling duplicate key processing properly
  • Ignoring file status after START operations
  • Not testing with large data volumes
  • Creating keys that are rarely used
  • Not considering maintenance overhead of multiple keys

Related COBOL Concepts

  • INDEXED files - File organization supporting alternate keys
  • RECORD KEY - Primary key for indexed files
  • START statement - Positioning for alternate key access
  • READ NEXT - Sequential reading using alternate keys
  • WITH DUPLICATES - Allowing duplicate alternate key values
  • Compound keys - Multiple field alternate keys
  • File status - Error handling for key operations
  • DYNAMIC access - Combined sequential and random access