Relative file operations in COBOL involve working with RRDS (Relative Record Data Set) files that provide direct access to records by relative record number (position). Each record has a fixed position identified by its relative record number (1, 2, 3, etc.), allowing you to read, write, update, or delete records by specifying the position. Understanding relative file operations is essential for working with lookup tables, fixed-size data structures, and applications where position-based access is appropriate in mainframe COBOL programs.
Relative files (RRDS) provide position-based access:
Relative files are useful when you know the record position or need array-like access to disk-based data.
Define relative files using ORGANIZATION IS RELATIVE:
1234567891011121314151617181920212223ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT LOOKUP-FILE ASSIGN TO LOOKUP.VSAM ORGANIZATION IS RELATIVE ACCESS MODE IS RANDOM RELATIVE KEY IS RECORD-NUMBER FILE STATUS IS LOOKUP-STATUS. DATA DIVISION. FILE SECTION. FD LOOKUP-FILE. 01 LOOKUP-RECORD. 05 STATE-CODE PIC X(2). 05 STATE-NAME PIC X(20). 05 STATE-TAX-RATE PIC V999. 05 FILLER PIC X(75). *> Fixed record length WORKING-STORAGE SECTION. 01 RECORD-NUMBER PIC 9(4). 01 LOOKUP-STATUS PIC XX. 88 FILE-OK VALUE '00'. 88 RECORD-NOT-FOUND VALUE '23'.
Key components:
Reading records by position:
1234567891011121314151617181920212223242526PROCEDURE DIVISION. MAIN-PARA. OPEN INPUT LOOKUP-FILE *> Read record at position 5 MOVE 5 TO RECORD-NUMBER READ LOOKUP-FILE INVALID KEY DISPLAY "Record not found at position: " RECORD-NUMBER NOT INVALID KEY DISPLAY "State Code: " STATE-CODE DISPLAY "State Name: " STATE-NAME DISPLAY "Tax Rate: " STATE-TAX-RATE END-READ *> Read record at position 10 MOVE 10 TO RECORD-NUMBER READ LOOKUP-FILE INVALID KEY DISPLAY "Record not found at position: " RECORD-NUMBER NOT INVALID KEY DISPLAY "Record 10: " STATE-NAME END-READ CLOSE LOOKUP-FILE STOP RUN.
For random access, set the RELATIVE KEY to the desired position, then READ. The record at that position is retrieved.
1234567891011121314151617181920212223SELECT LOOKUP-FILE ASSIGN TO LOOKUP.VSAM ORGANIZATION IS RELATIVE ACCESS MODE IS SEQUENTIAL RELATIVE KEY IS RECORD-NUMBER. PROCEDURE DIVISION. MAIN-PARA. OPEN INPUT LOOKUP-FILE *> Read records sequentially (1, 2, 3, etc.) PERFORM UNTIL END-OF-FILE READ LOOKUP-FILE NEXT AT END SET END-OF-FILE TO TRUE NOT AT END DISPLAY "Position: " RECORD-NUMBER DISPLAY "State: " STATE-NAME *> Process record END-READ END-PERFORM CLOSE LOOKUP-FILE STOP RUN.
Sequential access reads records in order starting from position 1, advancing through positions 2, 3, 4, etc.
Writing records to specific positions:
1234567891011121314151617181920212223242526PROCEDURE DIVISION. MAIN-PARA. OPEN OUTPUT LOOKUP-FILE *> Write record at position 1 MOVE 1 TO RECORD-NUMBER MOVE 'TX' TO STATE-CODE MOVE 'TEXAS' TO STATE-NAME MOVE 0.0825 TO STATE-TAX-RATE WRITE LOOKUP-RECORD INVALID KEY DISPLAY "Error writing at position: " RECORD-NUMBER NOT INVALID KEY DISPLAY "Record written at position: " RECORD-NUMBER END-WRITE *> Write record at position 2 MOVE 2 TO RECORD-NUMBER MOVE 'CA' TO STATE-CODE MOVE 'CALIFORNIA' TO STATE-NAME MOVE 0.0725 TO STATE-TAX-RATE WRITE LOOKUP-RECORD END-WRITE CLOSE LOOKUP-FILE STOP RUN.
Set the RELATIVE KEY to the desired position, prepare the record data, then WRITE. The record is stored at that position.
Updating records requires reading first, then rewriting:
12345678910111213141516171819202122232425PROCEDURE DIVISION. MAIN-PARA. OPEN I-O LOOKUP-FILE *> Read record at position 5 MOVE 5 TO RECORD-NUMBER READ LOOKUP-FILE INVALID KEY DISPLAY "Record not found at position: " RECORD-NUMBER NOT INVALID KEY *> Modify record data MOVE 0.0900 TO STATE-TAX-RATE MOVE 'UPDATED' TO STATE-NAME *> Write updated record back REWRITE LOOKUP-RECORD INVALID KEY DISPLAY "Error updating record" NOT INVALID KEY DISPLAY "Record updated at position: " RECORD-NUMBER END-REWRITE END-READ CLOSE LOOKUP-FILE STOP RUN.
The update process: read the record, modify data in memory, then REWRITE to write it back to the same position.
Deleting records removes them from specific positions:
123456789101112131415PROCEDURE DIVISION. MAIN-PARA. OPEN I-O LOOKUP-FILE *> Delete record at position 10 MOVE 10 TO RECORD-NUMBER DELETE LOOKUP-FILE RECORD INVALID KEY DISPLAY "Record not found at position: " RECORD-NUMBER NOT INVALID KEY DISPLAY "Record deleted at position: " RECORD-NUMBER END-DELETE CLOSE LOOKUP-FILE STOP RUN.
DELETE removes the record at the specified position. The position becomes available for reuse, but other record positions remain unchanged.
Understanding when to use relative vs indexed files:
| Aspect | Relative Files | Indexed Files |
|---|---|---|
| Access method | By position (1, 2, 3, etc.) | By key value |
| Key type | RELATIVE KEY (numeric position) | RECORD KEY (data value) |
| Record order | By position | Sorted by key |
| Use when | Position is meaningful, lookup tables | Key-based access, meaningful keys |
| Flexibility | Less flexible, requires knowing position | More flexible, access by meaningful keys |
| Complexity | Simpler | More complex with indexes |
Complete example demonstrating relative file operations:
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133IDENTIFICATION DIVISION. PROGRAM-ID. RELATIVE-FILE-DEMO. ENVIRONMENT DIVISION. INPUT-OUTPUT SECTION. FILE-CONTROL. SELECT STATE-LOOKUP ASSIGN TO STATE.VSAM ORGANIZATION IS RELATIVE ACCESS MODE IS RANDOM RELATIVE KEY IS STATE-POSITION FILE STATUS IS STATE-STATUS. DATA DIVISION. FILE SECTION. FD STATE-LOOKUP. 01 STATE-RECORD. 05 STATE-CODE PIC X(2). 05 STATE-NAME PIC X(20). 05 STATE-POPULATION PIC 9(8). 05 FILLER PIC X(102). *> Total 132 bytes WORKING-STORAGE SECTION. 01 STATE-POSITION PIC 9(4). 01 STATE-STATUS PIC XX. 88 FILE-OK VALUE '00'. 88 RECORD-NOT-FOUND VALUE '23'. PROCEDURE DIVISION. MAIN-PARA. DISPLAY "=== RELATIVE FILE DEMONSTRATION ===" PERFORM INITIALIZE-FILE PERFORM ADD-RECORDS PERFORM READ-RECORDS PERFORM UPDATE-RECORD PERFORM DELETE-RECORD PERFORM FINALIZE STOP RUN. INITIALIZE-FILE. DISPLAY "Initializing state lookup file..." OPEN OUTPUT STATE-LOOKUP IF NOT FILE-OK DISPLAY "Error opening file: " STATE-STATUS STOP RUN END-IF. ADD-RECORDS. DISPLAY "Adding state records..." *> Add Texas at position 1 MOVE 1 TO STATE-POSITION MOVE 'TX' TO STATE-CODE MOVE 'TEXAS' TO STATE-NAME MOVE 29000000 TO STATE-POPULATION WRITE STATE-RECORD INVALID KEY DISPLAY "Error writing position 1" END-WRITE *> Add California at position 2 MOVE 2 TO STATE-POSITION MOVE 'CA' TO STATE-CODE MOVE 'CALIFORNIA' TO STATE-NAME MOVE 39000000 TO STATE-POPULATION WRITE STATE-RECORD END-WRITE *> Add New York at position 3 MOVE 3 TO STATE-POSITION MOVE 'NY' TO STATE-CODE MOVE 'NEW YORK' TO STATE-NAME MOVE 20000000 TO STATE-POPULATION WRITE STATE-RECORD END-WRITE CLOSE STATE-LOOKUP DISPLAY "Records added successfully". READ-RECORDS. DISPLAY "Reading state records..." OPEN INPUT STATE-LOOKUP *> Read position 1 MOVE 1 TO STATE-POSITION READ STATE-LOOKUP INVALID KEY DISPLAY "Position 1 not found" NOT INVALID KEY DISPLAY "Position 1: " STATE-NAME " (" STATE-CODE ")" END-READ *> Read position 2 MOVE 2 TO STATE-POSITION READ STATE-LOOKUP NOT INVALID KEY DISPLAY "Position 2: " STATE-NAME " (" STATE-CODE ")" END-READ CLOSE STATE-LOOKUP. UPDATE-RECORD. DISPLAY "Updating record at position 2..." OPEN I-O STATE-LOOKUP MOVE 2 TO STATE-POSITION READ STATE-LOOKUP NOT INVALID KEY *> Update population ADD 1000000 TO STATE-POPULATION REWRITE STATE-RECORD NOT INVALID KEY DISPLAY "Record updated: " STATE-NAME END-REWRITE END-READ CLOSE STATE-LOOKUP. DELETE-RECORD. DISPLAY "Deleting record at position 3..." OPEN I-O STATE-LOOKUP MOVE 3 TO STATE-POSITION DELETE STATE-LOOKUP RECORD INVALID KEY DISPLAY "Record not found at position 3" NOT INVALID KEY DISPLAY "Record deleted at position 3" END-DELETE CLOSE STATE-LOOKUP. FINALIZE. DISPLAY "=== DEMONSTRATION COMPLETE ===".
Follow these best practices:
12345678*> Use relative file as lookup table MOVE LOOKUP-INDEX TO RECORD-NUMBER READ LOOKUP-FILE INVALID KEY DISPLAY "Lookup value not found" NOT INVALID KEY *> Use LOOKUP-RECORD data END-READ
12345678910*> Process all records sequentially OPEN INPUT LOOKUP-FILE PERFORM UNTIL END-OF-FILE READ LOOKUP-FILE NEXT AT END SET END-OF-FILE TO TRUE NOT AT END *> Process record at RECORD-NUMBER END-READ END-PERFORM CLOSE LOOKUP-FILE
12345678*> Update record at known position MOVE UPDATE-POSITION TO RECORD-NUMBER READ LOOKUP-FILE NOT INVALID KEY *> Modify data MOVE NEW-DATA TO RECORD-FIELDS REWRITE LOOKUP-RECORD END-READ
Think of relative files like a row of numbered mailboxes:
So relative files are like a row of numbered mailboxes where you can go directly to any mailbox by its number!
Complete these exercises to reinforce your understanding:
Create a program that writes 10 records to a relative file at positions 1 through 10, then reads them back and displays each record.
Create a relative file that acts as a lookup table. Write state codes and names to specific positions, then create a lookup function that finds a state by position.
Create a program that reads a record from a relative file, modifies specific fields, and uses REWRITE to update it. Handle errors appropriately.
Create a program that processes all records in a relative file sequentially using READ NEXT, displaying each record's position and data.
Create a program that deletes a record from a relative file, then writes a new record to that same position, demonstrating position reuse.
1. What organization type is used for relative files?
2. What key is used to access relative file records?
3. What is the first record position in a relative file?
4. How do you read a record at position 5 in a relative file?
5. Can you use sequential access with relative files?
6. What happens when you delete a record in a relative file?