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:
- Invokes DFSORT (IBM's sort engine) as a subtask
- Either reads records from a USING file or calls your INPUT PROCEDURE to feed records via RELEASE
- Sorts records according to the specified keys
- 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:
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:
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:
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:
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:
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:
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:
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
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:
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:
//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.
