DD statements and DISP
Most of the JCL you write is DD statements. The COBOL program only knows DD names; the DD statement decides which dataset each one is, and what happens to that dataset before and after the step.
The common DD forms
//ACCTIN DD DSN=BANK.ACCOUNTS,DISP=SHR existing dataset
//REPORT DD DSN=BANK.REPORT,DISP=(NEW,CATLG,DELETE) new dataset
//SYSOUT DD SYSOUT=* to the spool
//CARDS DD DUMMY empty input, output discarded
//SYSIN DD * data inline in the JCL
20260924
/*
DSN (or DSNAME) is the dataset name: up to 44 characters in
qualifiers of 1–8 characters separated by dots.
DISP=(status,normal,abnormal)
Status says what state the dataset is in when the step starts:
| Status | Meaning |
|---|---|
NEW |
Create it. JCL error if it already exists |
OLD |
It exists; I want it exclusively (to rewrite or delete it) |
SHR |
It exists; others may read it at the same time |
MOD |
Append to it. If it doesn't exist, create it |
Normal disposition applies when the step ends, with any return code:
| Disposition | Meaning |
|---|---|
KEEP |
Keep it |
CATLG |
Keep it and record it in the catalog so later jobs find it by name |
DELETE |
Delete it |
PASS |
Keep it for a later step in this job (next lesson) |
Abnormal disposition applies only if the step abends. If you leave it out, the normal disposition is used for both.
The three positions are positional, so DISP=(,CATLG) means "status
defaulted to NEW, catalog it". DISP=SHR on its own means (SHR,KEEP).
Choosing dispositions
Think about the rerun. A job abends at 3 a.m.; someone fixes the problem and resubmits. Will it work?
- Output:
DISP=(NEW,CATLG,DELETE). After an abend the partial output is deleted, so the rerun'sNEWdoesn't fail with a duplicate name. - Input consumed by the step:
DISP=(OLD,DELETE,KEEP). It is deleted only once processed successfully; after an abend it is still there to rerun. - Reference data:
DISP=SHR, neverOLD.OLDlocks it and holds up every other job that reads it. - Logs and accumulating files:
DISP=(MOD,CATLG).
IEFBR14: the program that does nothing
IEFBR14 is a two-instruction IBM program that just returns. So why run
it? Because the system still allocates and disposes of every DD
in the step. That makes it the standard tool for creating and deleting
datasets:
//CLEANUP EXEC PGM=IEFBR14
//OLDREJ DD DSN=BANK.TRAN.REJECTS,DISP=(MOD,DELETE)
//NEWFILE DD DSN=BANK.TRAN.EMPTY,DISP=(NEW,CATLG)
Here DISP=(OLD,DELETE) would be a trap: on a night with no rejects the
job fails before anything runs:
IEF212I DELJOB DELETE DATA SET NOT FOUND - OLDREJ DSN=BANK.TRAN.REJECTS
and NEW on a dataset that already exists fails with DUPLICATE NAME ON
DIRECT ACCESS VOLUME.
What real NEW datasets also need
On z/OS a new dataset needs space and a record format, for example
SPACE=(TRK,(10,5),RLSE), DCB=(RECFM=FB,LRECL=80,BLKSIZE=0) and
UNIT=SYSDA, or a site default (SMS) that supplies them. The
simulator doesn't need them, but you'll see them on almost every
output DD at work. Also note that a real DD with no DISP at all
defaults to (NEW,DELETE): the dataset vanishes at the end of the
step. Always code DISP.
On the job
A frequent cause of a night-shift call is a rerun failing with
"duplicate name" because the first run used (NEW,CATLG,CATLG) and
left a half-written output behind. Many shops add an IEFBR14
cleanup step with DISP=(MOD,DELETE) at the start of the job so it
can always be rerun from the top.
Your task
Finish the daily transaction job. Every night it must:
CLEANUP: runIEFBR14to delete yesterday'sBANK.TRAN.REJECTS. On some nights there are no rejects and the dataset doesn't exist; the step must work either way. Use the DD nameOLDREJ.POST: runPOSTLOG, which reads the day's transactions, appends the valid ones to the history log and writes the invalid ones to a new rejects dataset:
| DD | Dataset | What should happen to it |
|---|---|---|
TRANIN |
BANK.TRAN.DAILY |
Must exist. Deleted once posted; kept if the step abends so it can be rerun |
TRANLOG |
BANK.TRAN.HISTORY |
Appended to. On the very first night it doesn't exist yet and must be created. Always cataloged |
REJECTS |
BANK.TRAN.REJECTS |
Created new and cataloged; deleted if the step abends |
SYSOUT |
the spool | SYSOUT=* |
Every record is 18 characters: account X(8), type X (D or C),
amount 9(7)V99. POSTLOG displays POSTLOG: nnnnn POSTED, nnnnn REJECTED.