SORT with input and output procedures
USING and GIVING copy records into and out of the sort unchanged. Real
jobs usually want more: drop the records you don't need before the
sort (less to sort, faster job), reshape them, and do something with the
sorted stream after, such as totals or a report, without writing an
intermediate file. That is what procedures are for.
SORT SORT-WORK
ON ASCENDING KEY SRT-POLICY
INPUT PROCEDURE IS SELECT-APPROVED
OUTPUT PROCEDURE IS WRITE-LISTING
You can mix and match: USING with OUTPUT PROCEDURE, or
INPUT PROCEDURE with GIVING.
Input procedure: RELEASE
The input procedure is a paragraph (or section) that SORT performs once. It
reads whatever it likes, builds the SD record, and RELEASEs each one
into the sort:
SELECT-APPROVED.
OPEN INPUT CLAIM-IN
PERFORM UNTIL END-OF-FILE
READ CLAIM-IN
AT END SET END-OF-FILE TO TRUE
NOT AT END
IF CLM-STATUS = "A"
MOVE CLM-POLICY TO SRT-POLICY
MOVE CLM-AMOUNT TO SRT-AMOUNT
RELEASE SORT-REC
END-IF
END-READ
END-PERFORM
CLOSE CLAIM-IN.
Because you build the SD record yourself, it does not have to match the input layout. Put the keys first, leave out fields nobody needs.
Output procedure: RETURN
When the input procedure ends, the sort runs. Then SORT performs the output
procedure, which RETURNs records one at a time in sorted order until
AT END:
WRITE-LISTING.
OPEN OUTPUT CLAIM-OUT
MOVE "N" TO WS-EOF
PERFORM UNTIL END-OF-FILE
RETURN SORT-WORK
AT END SET END-OF-FILE TO TRUE
NOT AT END
ADD SRT-AMOUNT TO WS-TOTAL
MOVE SRT-POLICY TO DL-POLICY
MOVE SRT-AMOUNT TO DL-AMOUNT
WRITE CLAIM-OUT-REC FROM WS-DETAIL
END-RETURN
END-PERFORM
CLOSE CLAIM-OUT.
A full program with both procedures:
IDENTIFICATION DIVISION.
PROGRAM-ID. BIGSORT.
ENVIRONMENT DIVISION.
INPUT-OUTPUT SECTION.
FILE-CONTROL.
SELECT SORT-WORK ASSIGN TO SORTWK1.
DATA DIVISION.
FILE SECTION.
SD SORT-WORK.
01 SORT-REC.
05 SRT-AMOUNT PIC 9(4).
WORKING-STORAGE SECTION.
01 WS-EOF PIC X VALUE "N".
PROCEDURE DIVISION.
MAIN-LOGIC.
SORT SORT-WORK ON DESCENDING KEY SRT-AMOUNT
INPUT PROCEDURE IS LOAD-AMOUNTS
OUTPUT PROCEDURE IS SHOW-AMOUNTS
STOP RUN.
LOAD-AMOUNTS.
MOVE 40 TO SRT-AMOUNT
RELEASE SORT-REC
MOVE 9000 TO SRT-AMOUNT
RELEASE SORT-REC
MOVE 7 TO SRT-AMOUNT
RELEASE SORT-REC.
SHOW-AMOUNTS.
PERFORM UNTIL WS-EOF = "Y"
RETURN SORT-WORK
AT END MOVE "Y" TO WS-EOF
NOT AT END DISPLAY SRT-AMOUNT
END-RETURN
END-PERFORM.
prints 9000, 0040, 0007.
Rules
RELEASEnames the record (like WRITE);RETURNnames the file (like READ).- Procedures open and close their own files; the SD file is never opened.
- RELEASE only inside the input procedure, RETURN only inside the output
procedure. Don't
GO TOout of them. - Put the procedures after the main paragraph and end the main paragraph
with
STOP RUN, so control never falls through into them.
On the job
An input procedure that filters is one of the cheapest performance
wins in batch: sorting 2 million records instead of 20 million can take
minutes off the critical path of the nightly schedule. In older code
the procedures are often SECTIONs performed with THRU an exit
paragraph; the logic is the same.
Your task
Claims handling wants a listing of approved claims only, grouped by policy with the largest claim first, and a total at the end.
DD CLAIMIN — line sequential, 23-byte records:
| Field | PIC | Notes |
|---|---|---|
CLM-ID |
X(6) |
|
CLM-POLICY |
X(8) |
|
CLM-STATUS |
X |
A approved, anything else skipped |
CLM-AMOUNT |
9(6)V99 |
DD CLAIMOUT — line sequential listing, 40-byte lines.
The starter has the files, an SD with a different layout from the input
(SRT-POLICY, SRT-AMOUNT, SRT-ID), the print lines, and the SORT
statement. Fill in the two procedures:
- Input procedure
SELECT-APPROVED: read every claim, count it inWS-READ; for approved claims count them inWS-APPROVED, move the fields intoSORT-RECandRELEASEit. - Output procedure
WRITE-LISTING:RETURNrecords in sorted order and write oneWS-DETAILline each, adding toWS-TOTAL; finish withWS-TOTAL-LINE.
Expected listing for the first test:
PL000100 C00005 1,500.75
PL000100 C00008 20.51
PL000100 C00002 20.50
PL000200 C00004 100.00
PL000300 C00001 1,250.00
PL000300 C00007 9.99
TOTAL 6 CLAIMS 2,901.75
and on stdout: READ: 008 APPROVED: 006.