COBOLMainframe

COBOL SORT and MERGE: Complete Guide with JCL and DFSORT

TT
TopicTrick
COBOL SORT and MERGE: Complete Guide with JCL and DFSORT

The COBOL SORT statement is one of the most powerful features in the language — it provides a complete, in-program sort facility backed by DFSORT on z/OS. Rather than writing sorted data to a file and submitting a separate sort job, COBOL programs can sort data internally, apply pre-sort and post-sort logic, and continue processing in a single step. This guide covers the full SORT and MERGE facility with practical examples.

How COBOL SORT Works

When COBOL encounters a SORT statement, it:

  1. Invokes DFSORT (IBM's sort engine) as a subtask
  2. Either reads records from a USING file or calls your INPUT PROCEDURE to feed records via RELEASE
  3. Sorts records according to the specified keys
  4. Either writes sorted records to a GIVING file or calls your OUTPUT PROCEDURE to receive records via RETURN

The sort uses temporary work datasets (defined in JCL SORTWK01–SORTWK06 DD statements) for intermediate processing.

Sort File Declaration

Every SORT statement needs a sort work file declared with SELECT and SD:

cobol
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
    SELECT SORT-WORK-FILE
        ASSIGN TO SORTWORK.

    SELECT EMPLOYEE-FILE
        ASSIGN TO EMPLIN
        ORGANIZATION IS SEQUENTIAL
        FILE STATUS IS WS-EMP-STATUS.

    SELECT SORTED-OUTPUT-FILE
        ASSIGN TO EMPOUT
        ORGANIZATION IS SEQUENTIAL
        FILE STATUS IS WS-OUT-STATUS.

DATA DIVISION.
FILE SECTION.

SD  SORT-WORK-FILE
    RECORD CONTAINS 100 CHARACTERS.
01  SORT-WORK-RECORD.
    05 SWR-DEPT-CODE     PIC X(4).
    05 SWR-EMPLOYEE-ID   PIC X(8).
    05 SWR-LAST-NAME     PIC X(20).
    05 SWR-SALARY        PIC S9(9)V99 COMP-3.
    05 FILLER            PIC X(62).

FD  EMPLOYEE-FILE
    RECORD CONTAINS 100 CHARACTERS.
01  EMPLOYEE-RECORD      PIC X(100).

FD  SORTED-OUTPUT-FILE
    RECORD CONTAINS 100 CHARACTERS.
01  SORTED-OUTPUT-RECORD PIC X(100).

The SD record layout defines the structure of data flowing through the sort. The key fields (SWR-DEPT-CODE, SWR-SALARY) must exist as named fields within the SD record.

Simple SORT: USING and GIVING

The simplest form reads from one file, sorts, and writes to another with no PROCEDURE intervention:

cobol
PROCEDURE DIVISION.
MAIN-LOGIC.
    SORT SORT-WORK-FILE
        ON ASCENDING KEY SWR-DEPT-CODE
        ON ASCENDING KEY SWR-LAST-NAME
        USING    EMPLOYEE-FILE
        GIVING   SORTED-OUTPUT-FILE
    STOP RUN.

COBOL automatically opens EMPLOYEE-FILE, reads all records, sorts them by department then name, and writes the sorted output to SORTED-OUTPUT-FILE. No OPEN, READ, or WRITE statements are needed — SORT handles the entire I/O lifecycle.

Multiple keys with mixed directions:

cobol
SORT SORT-WORK-FILE
    ASCENDING  KEY SWR-DEPT-CODE
    DESCENDING KEY SWR-SALARY
    ASCENDING  KEY SWR-LAST-NAME
    USING    EMPLOYEE-FILE
    GIVING   SORTED-OUTPUT-FILE.

This sorts by department ascending, then by salary descending (highest paid first within each department), then alphabetically within ties.

INPUT PROCEDURE

When you need to filter or transform records before sorting, replace USING with INPUT PROCEDURE:

cobol
SORT SORT-WORK-FILE
    ASCENDING KEY SWR-DEPT-CODE
    ASCENDING KEY SWR-SALARY
    INPUT PROCEDURE IS PREPARE-SORT-INPUT
    GIVING SORTED-OUTPUT-FILE.

PREPARE-SORT-INPUT SECTION.
    OPEN INPUT EMPLOYEE-FILE
    PERFORM UNTIL WS-EMP-EOF
        READ EMPLOYEE-FILE INTO WS-EMPLOYEE-WORK
            AT END SET WS-EMP-EOF TO TRUE
        END-READ
        IF NOT WS-EMP-EOF
            IF WS-EMP-STATUS-CODE = 'A'    *> active employees only
                MOVE CORRESPONDING WS-EMPLOYEE-WORK TO SORT-WORK-RECORD
                RELEASE SORT-WORK-RECORD
            END-IF
        END-IF
    END-PERFORM
    CLOSE EMPLOYEE-FILE.

RELEASE is the verb that sends a record into the sort. You RELEASE from within the INPUT PROCEDURE; never use WRITE to the sort file.

RELEASE

RELEASE writes a record to the sort input stream:

cobol
RELEASE SORT-WORK-RECORD.

*> Or RELEASE FROM a working-storage area:
RELEASE SORT-WORK-RECORD FROM WS-SORT-INPUT-AREA.

RELEASE FROM moves the working-storage field into the SD record and releases it in one step.

OUTPUT PROCEDURE

When you need to process sorted records before writing them, replace GIVING with OUTPUT PROCEDURE:

cobol
SORT SORT-WORK-FILE
    ASCENDING KEY SWR-DEPT-CODE
    INPUT PROCEDURE IS PREPARE-SORT-INPUT
    OUTPUT PROCEDURE IS PRODUCE-DEPARTMENT-REPORT.

PRODUCE-DEPARTMENT-REPORT SECTION.
    OPEN OUTPUT REPORT-FILE
    MOVE SPACES TO WS-CURRENT-DEPT
    MOVE ZERO TO WS-DEPT-TOTAL

    PERFORM UNTIL WS-SORT-EOF
        RETURN SORT-WORK-FILE INTO WS-SORTED-EMPLOYEE
            AT END SET WS-SORT-EOF TO TRUE
        END-RETURN

        IF NOT WS-SORT-EOF
            IF SWR-DEPT-CODE NOT = WS-CURRENT-DEPT
                IF WS-CURRENT-DEPT NOT = SPACES
                    PERFORM WRITE-DEPT-SUBTOTAL
                END-IF
                MOVE SWR-DEPT-CODE TO WS-CURRENT-DEPT
                MOVE ZERO TO WS-DEPT-TOTAL
            END-IF
            PERFORM WRITE-EMPLOYEE-LINE
            ADD SWR-SALARY TO WS-DEPT-TOTAL
        END-IF
    END-PERFORM

    IF WS-CURRENT-DEPT NOT = SPACES
        PERFORM WRITE-DEPT-SUBTOTAL
    END-IF
    CLOSE REPORT-FILE.

RETURN

RETURN is the verb that reads the next sorted record from the sort output stream:

cobol
RETURN SORT-WORK-FILE
    AT END SET WS-SORT-EOF TO TRUE
END-RETURN.

*> Or RETURN INTO a working-storage area:
RETURN SORT-WORK-FILE INTO WS-SORTED-WORK-AREA
    AT END SET WS-SORT-EOF TO TRUE
END-RETURN.

The sequence inside an OUTPUT PROCEDURE is: RETURN → process → RETURN → process → ... → AT END when exhausted.

Complete Example: Salary Report by Department

cobol
PROCEDURE DIVISION.

MAIN-LOGIC.
    SORT SORT-WORK-FILE
        ASCENDING  KEY SWR-DEPT-CODE
        DESCENDING KEY SWR-SALARY
        ASCENDING  KEY SWR-LAST-NAME
        INPUT  PROCEDURE IS LOAD-ACTIVE-EMPLOYEES
        OUTPUT PROCEDURE IS PRODUCE-SALARY-REPORT
    STOP RUN.

LOAD-ACTIVE-EMPLOYEES SECTION.
    OPEN INPUT EMPLOYEE-FILE
    PERFORM UNTIL WS-EMP-EOF
        READ EMPLOYEE-FILE INTO WS-EMP-WORK
            AT END SET WS-EMP-EOF TO TRUE
        END-READ
        IF NOT WS-EMP-EOF
            EVALUATE TRUE
                WHEN WS-EMP-WORK-STATUS = 'A'
                    MOVE WS-EMP-WORK-DEPT   TO SWR-DEPT-CODE
                    MOVE WS-EMP-WORK-ID     TO SWR-EMPLOYEE-ID
                    MOVE WS-EMP-WORK-NAME   TO SWR-LAST-NAME
                    MOVE WS-EMP-WORK-SALARY TO SWR-SALARY
                    RELEASE SORT-WORK-RECORD
                    ADD 1 TO WS-RECORDS-RELEASED
                WHEN OTHER
                    ADD 1 TO WS-RECORDS-SKIPPED
            END-EVALUATE
        END-IF
    END-PERFORM
    CLOSE EMPLOYEE-FILE.

PRODUCE-SALARY-REPORT SECTION.
    OPEN OUTPUT REPORT-FILE
    PERFORM WRITE-REPORT-HEADER
    MOVE SPACES TO WS-PREV-DEPT
    MOVE ZERO TO WS-GRAND-TOTAL WS-DEPT-TOTAL WS-DEPT-COUNT

    PERFORM UNTIL WS-SORT-EOF
        RETURN SORT-WORK-FILE INTO WS-SORTED-EMP
            AT END SET WS-SORT-EOF TO TRUE
        END-RETURN

        IF NOT WS-SORT-EOF
            IF SWR-DEPT-CODE NOT = WS-PREV-DEPT
                IF WS-PREV-DEPT NOT = SPACES
                    PERFORM WRITE-DEPT-BREAK
                END-IF
                PERFORM WRITE-DEPT-HEADER
                MOVE SWR-DEPT-CODE TO WS-PREV-DEPT
                MOVE ZERO TO WS-DEPT-TOTAL WS-DEPT-COUNT
            END-IF
            PERFORM FORMAT-AND-WRITE-DETAIL-LINE
            ADD SWR-SALARY TO WS-DEPT-TOTAL WS-GRAND-TOTAL
            ADD 1 TO WS-DEPT-COUNT WS-TOTAL-COUNT
        END-IF
    END-PERFORM

    IF WS-PREV-DEPT NOT = SPACES
        PERFORM WRITE-DEPT-BREAK
    END-IF
    PERFORM WRITE-GRAND-TOTAL
    CLOSE REPORT-FILE.

MERGE Statement

MERGE combines two or more already-sorted files into a single sorted output. It is faster than sorting because the input files are assumed to be in the correct order:

cobol
ENVIRONMENT DIVISION.
FILE-CONTROL.
    SELECT MERGE-WORK-FILE ASSIGN TO MERGWRK.
    SELECT SORTED-FILE-1   ASSIGN TO SORTIN1.
    SELECT SORTED-FILE-2   ASSIGN TO SORTIN2.
    SELECT SORTED-FILE-3   ASSIGN TO SORTIN3.
    SELECT MERGED-OUTPUT   ASSIGN TO MERGEOUT.

DATA DIVISION.
FILE SECTION.
SD  MERGE-WORK-FILE
    RECORD CONTAINS 100 CHARACTERS.
01  MERGE-RECORD.
    05 MR-DATE          PIC 9(8).
    05 MR-ACCOUNT-ID    PIC X(10).
    05 FILLER           PIC X(82).

PROCEDURE DIVISION.
MAIN-LOGIC.
    MERGE MERGE-WORK-FILE
        ASCENDING KEY MR-DATE
        ASCENDING KEY MR-ACCOUNT-ID
        USING SORTED-FILE-1
              SORTED-FILE-2
              SORTED-FILE-3
        GIVING MERGED-OUTPUT
    STOP RUN.

MERGE supports OUTPUT PROCEDURE but not INPUT PROCEDURE — the input files must already be sorted in the specified key order.

JCL for SORT

The JCL that runs a COBOL program containing SORT must include sort work DD statements:

jcl
//RUNPGM  EXEC PGM=ACCTPROC
//STEPLIB  DD DSN=PROD.LOADLIB,DISP=SHR
//EMPLIN   DD DSN=PROD.EMPLOYEE.DATA,DISP=SHR
//EMPOUT   DD DSN=PROD.SORTED.EMPLOYEE,DISP=(NEW,CATLG),
//            DCB=(RECFM=FB,LRECL=100,BLKSIZE=27900)
//SORTWORK DD UNIT=SYSDA,SPACE=(CYL,(10,5))
//SORTWK01 DD UNIT=SYSDA,SPACE=(CYL,(10,5))
//SORTWK02 DD UNIT=SYSDA,SPACE=(CYL,(10,5))
//SORTWK03 DD UNIT=SYSDA,SPACE=(CYL,(10,5))
//SYSOUT   DD SYSOUT=*

DFSORT uses SORTWK01 through SORTWK06 as work datasets. Allocate at least 2–3 times the input data size across the sort work files. Using separate volumes for each SORTWK dataset maximizes parallel I/O performance.

Next Steps

SORT and MERGE complete the file processing toolkit. The next step is modular programming — calling subprograms with CALL, passing parameters BY REFERENCE and BY CONTENT, and the LINKAGE SECTION. See COBOL Subprograms, or return to the COBOL Mastery course.