Relative files and COBOL

The set-up

COBOL interfaces with relative files very well. First, COBOL needs to know that a particular file is a relative file. This is done in the SELECT statement. Add the following clauses:


      ORGANIZATION IS RELATIVE
      ACCESS IS RANDOM
      RELATIVE KEY IS working-storage-field.

ORGANIZATION tells COBOL how the file is physically organized. ACCESS tells COBOL how you will be accessing the file (logically organized). RANDOM means you will be accessing the file directly, not sequentially.

Instead of RANDOM you can have ACCESS IS SEQUENTIAL and then have your program treat the file as if it were any sequential file. This can be extremely useful at times. If ACCESS IS SEQUENTIAL then do not specify a RELATIVE KEY.

The RELATIVE KEY cannot be part of the record itself, it must be a numeric working-storage field. Make it as small as possible, if it is defined as a PIC 9(9) then COBOL will try to reserve enough space for a trillion records when the file is opened.

Opening relative files

Relative files can be opened as either INPUT or OUTPUT. There is also a third option, I-O, which stands for input/output. This allows you to read, write, update and delete records from the file in the same program.

Using the relative key

Whenever a READ or WRITE is issued COBOL checks the value of the RELATIVE KEY field and then attempts to read from or write to that record slot. The RELATIVE KEY is a record position, and the count starts at 1. So the desired value must be in that field before the READ or WRITE is issued.

Determining if the file operation was a success

After any I/O with a relative file the program must check that the operation was successful. At a minimum, the READ or WRITE must include an INVALID KEY clause which contains one statement to be executed in case the file operation was not successful. There is also a NOT INVALID KEY clause. If both are used, INVALID KEY comes first.


      MOVE HASH-VALUE TO WS-REL-KEY.
      READ RELATIVE-FILE
          INVALID KEY     PERFORM 300-RECORD-NOT-FOUND
          NOT INVALID KEY PERFORM 200-RECORD-FOUND
      END-READ.

Normally an invalid key condition on a read will be caused by the record slot not having a record. This may or may not be a disaster, depending on the program function, but it needs to be handled by code and not by having the program abend. Note that non-sequential reads do not use an AT END or NOT AT END clause.

An unsuccessful WRITE normally means that a record is already residing in that record slot. COBOL prevents the overlaying of one record with another using a WRITE.

For the purposes of this class the above method (INVALID KEY/NOT INVALID KEY) is sufficient but in the 'real world' you will want to be more careful. There are MANY things that can go wrong with non-sequential file I/O and you will want to check to see exactly what went wrong, or at least check for a couple of specific things that can go wrong.

This is done with a file status, a code that the system returns after any file I/O. If you've ever received a file error message while running a COBOL program the error number you're given is the file status. Click here to see a list of common file errors. If you are going to use the file status another clause must be added to the SELECT statement:


      FILE STATUS IS working-storage-field

This working-storage field is a PIC X(2). This field gets populated by the system automatically, just interrogate it after the file operation. Do not specify a FILE STATUS if ACCESS IS SEQUENTIAL.


      MOVE HASH-VALUE TO WS-REL-KEY.
      READ RELATIVE-FILE.

      EVALUATE WS-FILE-STATUS
         WHEN '00'
            PERFORM 200-RECORD-FOUND
         WHEN '23'
            PERFORM 300-RECORD-NOT-FOUND
         WHEN '30'
            DISPLAY 'HARDWARE FAILURE'
            STOP RUN
         WHEN '47'
            DISPLAY 'FILE OPEN IN WRONG MODE FOR READ'
            STOP RUN
         WHEN '92'
            DISPLAY 'FILE NOT OPEN'
            STOP RUN
         WHEN OTHER
            DISPLAY 'UNEXPECTED FILE STATUS ' WS-FILE-STATUS
            STOP RUN
      END-EVALUATE.

Whenever displaying errors be sure to include as much information as possible (record key, relative key, which file, attempted operation, etc.).

The INVALID KEY is triggered when the first character of the file status is not a '0'. Else is is a NOT INVLAID KEY situation. The first method also uses the file status, you just have no control over how it is used.

Deleting and updating records

Deleting and updating records requires that the file was opened as I-O.

COBOL has a DELETE statement which will delete the current record from the file. There must be a current record so a successful READ must precede the DELETE. This will also ensure that the record to be deleted exists in the first place.


      DELETE file-name RECORD

The DELETE does support the INVALID KEY/NOT INVLAID KEY clauses or you can explicitly check the file status after the DELETE. There is an END-DELETE delimiter.

COBOL has a REWRITE statement which will update the current record in the file (known as 'updating in place'). There must be a current record so a successful READ must precede the REWRITE. Note that the REWRITE changes the data on an existing record, it does not add a new record to the file (that's what a WRITE does).


      REWRITE file-name

The REWRITE does support the INVALID KEY/NOT INVLAID KEY clauses or you can explicitly check the file status after the REWRITE. There is an END-REWRITE delimiter.