cheat sheet

IDCAMS

Define, copy, list, alter, and delete VSAM clusters and general datasets — the everyday utility for catalog and dataset lifecycle on z/OS.

IDCAMS — Access Method Services for VSAM

What it is

IDCAMS (the program name; "Access Method Services" or AMS is the language) is IBM's command-driven utility for managing VSAM datasets and the integrated catalog on z/OS — define, alter, list, copy, print, delete, repair, every lifecycle operation lives here. It is one of the few z/OS utilities you run every day across roles: DBAs use it to allocate KSDS clusters under CICS and Db2, batch programmers use REPRO to copy and reshape sequential files, and system programmers use LISTCAT to investigate where a dataset actually lives. Reach for IDCAMS whenever the verb in your head is "define", "list", "copy", or "delete" against a dataset. For pure PDS member manipulation prefer IEBCOPY; for byte-level dataset inspection prefer ISPF Browse or DFSORT.

Invoking IDCAMS

IDCAMS runs as PGM=IDCAMS from JCL, or via TSO IDCAMS interactively. It always reads commands from the SYSIN DD and writes reports to SYSPRINT. The same SYSIN can contain any number of commands; each is independent and its return code rolls up via the LASTCC and MAXCC symbols.

text
//ALICEJ01 JOB (ACCT),'ALICE',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//IDCAMS   EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  LISTCAT ENTRIES('ALICE.MASTER.KSDS') ALL
/*

Output:

text
IDCAMS  SYSTEM SERVICES                                  TIME: 10:23:11
LISTCAT ENTRIES('ALICE.MASTER.KSDS') ALL
CLUSTER ------- ALICE.MASTER.KSDS
... attributes ...
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

Interactive use is identical but with the commands typed directly at the TSO prompt:

text
TSO IDCAMS
ENTER COMMAND>
  LISTCAT ENTRIES('ALICE.MASTER.KSDS') ALL

Output: (same LISTCAT report, displayed on the terminal)

Command structure

Every IDCAMS command is a verb followed by positional and keyword parameters. Continuation is a trailing hyphen (-); comments are /* ... */. Keyword arguments can usually be abbreviated to three or four letters (e.g. RECORDSIZERECSZ) but most shops write them out for readability.

text
VERB  POSITIONAL -
      (NAME(...)               -
       <parm1>                 -
       <parm2>)                -
      <secondary-parm1>        -
      <secondary-parm2>

The verbs split into four buckets: define (DEFINE CLUSTER, DEFINE AIX, DEFINE PATH, DEFINE GDG, DEFINE ALIAS, DEFINE PAGESPACE), list/inspect (LISTCAT, PRINT, EXAMINE), copy/load (REPRO, EXPORT, IMPORT, BLDINDEX), and modify/destroy (ALTER, DELETE, RENAME, VERIFY).

DEFINE CLUSTER — VSAM allocation

DEFINE CLUSTER allocates a new VSAM dataset of one of four organizations: KSDS (keyed, the default for most CICS files), ESDS (entry-sequenced, append-only), RRDS (relative-record, fixed-length numbered slots), and LDS (linear dataset, used by Db2 tablespaces). The cluster is the logical object; the data component and (for KSDS/AIX) the index component are physical sub-allocations.

text
//DEFKSDS  EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DEFINE CLUSTER -
    ( NAME(ALICE.MASTER.KSDS)             -
      INDEXED                              -
      KEYS(10 0)                           -
      RECORDSIZE(80 256)                   -
      RECORDS(5000 500)                    -
      FREESPACE(20 10)                     -
      SHAREOPTIONS(2 3)                    -
      VOLUMES(SHARED)                      -
      SPEED                                -
    )                                      -
    DATA  ( NAME(ALICE.MASTER.KSDS.DATA)  -
            CISZ(4096) )                   -
    INDEX ( NAME(ALICE.MASTER.KSDS.INDEX) -
            CISZ(1024) )
/*

Output:

text
IDC0508I DATA ALLOCATION STATUS FOR VOLUME SMS001 IS 0
IDC0509I INDEX ALLOCATION STATUS FOR VOLUME SMS001 IS 0
IDC0181I STORAGECLASS USED IS SCSTND
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

The important knobs:

ParameterMeaning
INDEXED / NONINDEXED / NUMBERED / LINEARKSDS / ESDS / RRDS / LDS
KEYS(length offset)Primary key length and offset (KSDS only)
RECORDSIZE(avg max)Average and maximum logical record length
RECORDS(prim sec)Primary and secondary allocation in records
TRACKS(prim sec)Same in tracks
CYLINDERS(prim sec)Same in cylinders
FREESPACE(ci% ca%)Percent free per CI and per CA — leaves room for inserts
SHAREOPTIONS(cross-region cross-system)Concurrent-access policy (see below)
VOLUMES(vol1 vol2) / SHAREDVolume placement; under SMS use the SMS class
STORAGECLASS() / MGMTCLASS() / DATACLASS()SMS classes (preferred when SMS is active)
SPEED / RECOVERYLoad mode — SPEED skips preformat, faster initial load
REUSE / NOREUSEAllow the cluster to be reopened in load mode
SPANNED / NOSPANNEDPermit records to span CIs
IMBED / NOIMBED(Deprecated) embed sequence set with data
REPLICATE / NOREPLICATE(Deprecated) replicate index records
CONTROLINTERVALSIZE(n) / CISZ(n)CI size in bytes (512 — 32768)
BUFFERSPACE(n)Minimum buffer pool size at open
ERASE / NOERASEOverwrite data area on delete

SHAREOPTIONS quick decoder

The two SHAREOPTIONS numbers define cross-region and cross-system concurrent access. Choosing the right pair is one of the most common DBA discussions for a new file.

PairMeaning
(1 3)One updater + many readers, single system
(2 3)One updater + many readers, multi-system
(3 3)Many updaters, anything goes — applications must serialize themselves
(4 3)Many updaters, VSAM enforces serial buffering (slower)

(3 3) is the common CICS choice when the region itself handles locking; never use it for batch programs that update directly without serialization.

DEFINE ALTERNATEINDEX and DEFINE PATH

An Alternate Index (AIX) is a KSDS that maps non-primary key values back to primary keys of a base cluster — letting an application read records by, say, customer-email when the base is keyed by customer-id. A PATH is the named view that joins the AIX to the base cluster; programs open the path, not the AIX directly.

text
//DEFAIX   EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DEFINE AIX                                            -
    ( NAME(ALICE.MASTER.AIX.EMAIL)                       -
      RELATE(ALICE.MASTER.KSDS)                          -
      KEYS(40 10)                                        -
      RECORDSIZE(50 250)                                 -
      RECORDS(5000 500)                                  -
      UPGRADE                                            -
      NONUNIQUEKEY                                       -
      SHAREOPTIONS(2 3)                                  -
    )                                                    -
    DATA  ( NAME(ALICE.MASTER.AIX.EMAIL.DATA)  )         -
    INDEX ( NAME(ALICE.MASTER.AIX.EMAIL.INDEX) )

  DEFINE PATH                                            -
    ( NAME(ALICE.MASTER.PATH.EMAIL)                      -
      PATHENTRY(ALICE.MASTER.AIX.EMAIL)                  -
      UPDATE                                             -
    )

  BLDINDEX                                               -
    INDATASET(ALICE.MASTER.KSDS)                         -
    OUTDATASET(ALICE.MASTER.AIX.EMAIL)
/*

Output:

text
IDC0181I STORAGECLASS USED IS SCSTND
IDC01551I AIX ALICE.MASTER.AIX.EMAIL HAS BEEN SUCCESSFULLY DEFINED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0
IDC01558I BLDINDEX COMPLETE, RECORDS PROCESSED = 5000

UPGRADE means VSAM automatically updates the AIX whenever the base cluster changes — almost always what you want. NONUNIQUEKEY allows multiple base records to share an alt-key value (e.g. multiple customers with the same email); UNIQUEKEY rejects duplicates at load and update.

BLDINDEX reads the base cluster end-to-end and populates the AIX. It is the only command that does this — the AIX is empty until you build it. After load, UPGRADE keeps it in sync going forward.

REPRO — copy, load, unload

REPRO is the universal copy verb: it copies any sequential or VSAM dataset to any other (with format conversion handled automatically). It's how you load data into a freshly defined KSDS from a flat file, how you unload a KSDS for backup, and how you copy one PDS member to a sequential dataset for transport.

text
//LOAD     EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//FLATIN   DD   DSN=ALICE.MASTER.FLAT,DISP=SHR
//KSDSOUT  DD   DSN=ALICE.MASTER.KSDS,DISP=SHR
//SYSIN    DD   *
  REPRO INFILE(FLATIN) OUTFILE(KSDSOUT)
/*

Output:

text
IDC0005I NUMBER OF RECORDS PROCESSED WAS 5000
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

The DD-name form is preferable for typed datasets (with DCB on the JCL) but you can also reference datasets directly:

text
  REPRO INDATASET(ALICE.MASTER.KSDS)         -
        OUTDATASET(ALICE.MASTER.BACKUP.FLAT) -
        REPLACE

Output:

text
IDC0005I NUMBER OF RECORDS PROCESSED WAS 5000

Useful REPRO sub-parameters:

ParameterEffect
FROMKEY(x) TOKEY(y)Copy only records with primary key in this range
FROMADDRESS(x) TOADDRESS(y)Same, by RBA
SKIP(n)Skip the first n records
COUNT(n)Copy at most n records
REPLACEOverwrite duplicates in the output cluster
NOREPLACESkip duplicates (default)
REUSEOpen the output cluster in load-mode, resetting it

LISTCAT — what is this thing, really

LISTCAT queries the integrated catalog. You can list a single entry's full attributes, every entry under a high-level qualifier, or just the names matching a pattern. It is the single best command to investigate "why is my job seeing a different copy of this dataset than I expect".

text
  LISTCAT ENTRIES('ALICE.MASTER.KSDS') ALL
  LISTCAT LEVEL('ALICE') NAMES
  LISTCAT LEVEL('ALICE.MASTER') ALL
  LISTCAT ENTRIES('ALICE.MASTER.KSDS') VOLUME
  LISTCAT ENTRIES('ALICE.MASTER.KSDS') HISTORY
  LISTCAT ENTRIES('ALICE.GDG.BASE') GDG ALL
  LISTCAT CLUSTER LEVEL('ALICE')
  LISTCAT AIX LEVEL('ALICE')
  LISTCAT PATH LEVEL('ALICE')
  LISTCAT ALIAS LEVEL('ALICE')
  LISTCAT USERCATALOG LEVEL('UCAT.PROD.*')

Output:

text
LISTING FROM CATALOG -- ICFCAT.MASTER

CLUSTER ------- ALICE.MASTER.KSDS
     IN-CAT --- ICFCAT.MASTER
     HISTORY
       DATASET-OWNER-----ALICE       CREATION--------2026.144
       RELEASE----------------2       EXPIRATION------0000.000
     SMSDATA
       STORAGECLASS-----SCSTND       MANAGEMENTCLASS--MCSTND
       DATACLASS--------DCSTND       LBACKUP ---0000.000.0000
     RLSDATA
       LOG--------------------NULL    LOGSTREAMID---------(NULL)
     PROTECTION-PSWD-----(NULL)      RACF----------------(YES)
     ASSOCIATIONS
       DATA-----ALICE.MASTER.KSDS.DATA
       INDEX----ALICE.MASTER.KSDS.INDEX

DATA --------- ALICE.MASTER.KSDS.DATA
     ATTRIBUTES
       KEYLEN----------------10       AVGLRECL--------------80
       MAXLRECL-------------256       BUFSPACE-----------12288
       CISIZE--------------4096       CI/CA-----------------72
       SHROPTNS(2,3)        SPEED    UNORDERED  NOREUSE   NONSPANNED
     STATISTICS
       REC-TOTAL------------5000       SPLITS-CI--------------0
       REC-DELETED------------0       SPLITS-CA--------------0
       REC-INSERTED-----------0       FREESPACE-%CI-------20
       REC-UPDATED------------0       FREESPACE-%CA-------10
     ALLOCATION
       SPACE-TYPE--------RECORD       HI-A-RBA---------2949120
       SPACE-PRI------------5000       HI-U-RBA---------2949120
       SPACE-SEC-------------500
     VOLUME
       VOLSER------------SMS001      DEVTYPE-------X'3010200F'
Display optionShows
NAMESJust the entry names — fast
VOLUMEAdds volume serials
ALLOCATIONAdds RBA, allocation, splits, free space
HISTORYCreation date, expiration, owner
ALLEverything — attributes, statistics, allocation, volume

Filter by type with CLUSTER / DATA / INDEX / AIX / PATH / ALIAS / GDG / NONVSAM / PAGESPACE / USERCATALOG.

PRINT writes the records of a dataset to SYSPRINT in three optional formats: CHARACTER (EBCDIC text), HEX, or DUMP (side-by-side hex + EBCDIC, the most useful for VSAM debugging). Useful when ISPF Browse won't open the file or when you want a permanent log of "the file looked like this at this moment".

text
  PRINT INDATASET(ALICE.MASTER.KSDS)        -
        FROMKEY(0000000001)                  -
        TOKEY(0000000010)                    -
        DUMP

  PRINT INDATASET(ALICE.MASTER.FLAT)         -
        CHARACTER                            -
        COUNT(5)

Output:

text
KEY OF RECORD - F0F0F0F0F0F0F0F0F0F1
0000  E2D4C9E3 C840400 ... CUSTOMER NAME etc. ASCII rendered to side
KEY OF RECORD - F0F0F0F0F0F0F0F0F0F2
...
IDC0005I NUMBER OF RECORDS PROCESSED WAS 10

SKIP(n) and COUNT(n) work the same as in REPRO. OUTFILE(dd) writes to a sequential dataset instead of SYSPRINT.

DELETE — remove with consequences

DELETE removes catalog entries and (optionally) scratches the underlying physical dataset. Without parameters it deletes the catalog entry only; with PURGE it ignores expiration date; with ERASE it overwrites the data area first.

text
  DELETE ALICE.MASTER.OLD.KSDS                          (* basic *)
  DELETE ALICE.MASTER.OLD.KSDS  PURGE                   (* ignore exp date *)
  DELETE ALICE.MASTER.OLD.KSDS  ERASE                   (* overwrite first *)
  DELETE ALICE.MASTER.OLD.KSDS  CLUSTER                 (* explicit type *)
  DELETE 'ALICE.OLD.*'         MASK                    (* pattern match *)
  DELETE 'ALICE.NONVSAM'       NONVSAM SCRATCH         (* uncatalog + scratch *)
  DELETE 'ALICE.NOENTRY'       NOSCRATCH               (* uncatalog only *)
  DELETE ALICE.GDG.BASE        GDG FORCE               (* GDG and all gens *)
  DELETE ALICE.MASTER.AIX.EMAIL AIX                    (* drop the AIX *)
  DELETE ALICE.MASTER.PATH.EMAIL PATH                  (* drop the path *)

Output:

text
IDC0550I ENTRY (D) ALICE.MASTER.OLD.KSDS.DATA DELETED
IDC0550I ENTRY (I) ALICE.MASTER.OLD.KSDS.INDEX DELETED
IDC0550I ENTRY (C) ALICE.MASTER.OLD.KSDS DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

For VSAM clusters the index and data components are deleted automatically when the cluster is. For AIX and PATH, drop them individually before the base cluster (or use CLUSTER FORCE).

ModifierBehavior
PURGEOverride expiration / retention
ERASEOverwrite physical area before scratch
SCRATCH / NOSCRATCHScratch DASD (default) vs leave it
FORCEFor GDGs, delete base and all generations
RECOVERY / NORECOVERYDSCB recovery option
MASKTreat pattern as wildcard for bulk delete

ALTER and RENAME

ALTER modifies attributes of an existing cluster without re-defining it; RENAME changes the name only. Most attribute changes do not require unload/reload, but a few (e.g. CISIZE, KEYS, RECORDSIZE) cannot be altered — you must redefine and reload.

text
  ALTER ALICE.MASTER.KSDS SHAREOPTIONS(3 3)
  ALTER ALICE.MASTER.KSDS FREESPACE(30 20)
  ALTER ALICE.MASTER.KSDS ADDVOLUMES(SMS002)
  ALTER ALICE.MASTER.KSDS NULLIFY(OWNER)
  ALTER ALICE.MASTER.KSDS BUFFERSPACE(65536)

  ALTER ALICE.MASTER.OLD.KSDS NEWNAME(ALICE.MASTER.NEW.KSDS)
  ALTER ALICE.MASTER.NEW.KSDS.DATA NEWNAME(ALICE.MASTER.NEW.KSDS.DATA)
  ALTER ALICE.MASTER.NEW.KSDS.INDEX NEWNAME(ALICE.MASTER.NEW.KSDS.INDEX)

Output:

text
IDC0531I ENTRY ALICE.MASTER.KSDS ALTERED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

Renaming a VSAM cluster does not rename its DATA and INDEX components — you must alter each one separately. Forgetting this is one of the most common IDCAMS pitfalls.

EXAMINE and VERIFY

EXAMINE runs a structural integrity check on a KSDS — chases pointers through the index, validates control-interval headers, reports broken or out-of-sequence keys. VERIFY is lighter: it compares the catalog's "high used RBA" with the actual end-of-file and fixes the catalog if the dataset was left open across a crash.

text
  EXAMINE NAME(ALICE.MASTER.KSDS) INDEXTEST DATATEST ERRORLIMIT(100)
  VERIFY  DATASET(ALICE.MASTER.KSDS)

Output:

text
IDC01700I INDEXTEST BEGINS
IDC01707I INDEXTEST SUCCESSFUL, NO LOGICAL ERRORS DETECTED
IDC01702I DATATEST BEGINS
IDC01708I DATATEST SUCCESSFUL, NO LOGICAL ERRORS DETECTED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

IDC01548I VERIFY HIGH USED RBA = 2949120, HIGH ALLOCATED RBA = 2949120
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

Run VERIFY against any cluster that abended a job mid-update before re-running. Run EXAMINE periodically against critical KSDS files; CI/CA split corruption is rare but real.

DEFINE GENERATIONDATAGROUP

A GDG is a named series of generations of the same dataset. DEFINE GENERATIONDATAGROUP creates the empty base; JCL with (+1) allocates new generations against it.

text
  DEFINE GENERATIONDATAGROUP                  -
    ( NAME(ALICE.DAILY.BACKUP)                 -
      LIMIT(14)                                -
      SCRATCH                                  -
      NOEMPTY                                  -
    )

Output:

text
IDC0531I ENTRY ALICE.DAILY.BACKUP DEFINED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0
ParameterMeaning
LIMIT(n)Maximum generations to retain
SCRATCH / NOSCRATCHPhysically scratch rolled-off generations vs only uncatalog
EMPTY / NOEMPTYAt rollover, uncatalog all generations vs only the oldest
OWNER(id)Catalog owner ID
FOR(days) / TO(date)Default retention for new generations
EXTENDEDAllow up to 999 generations (otherwise capped at 255)

See the upcoming gdg article for the JCL-side reference patterns.

ALIAS, USERCATALOG, ALIAS chains

A USERCATALOG is a non-master catalog; an ALIAS routes a high-level qualifier to a specific catalog. Most sites direct each application's HLQ to a dedicated USERCATALOG so backups, recovery, and ownership are scoped.

text
  DEFINE USERCATALOG                                    -
    ( NAME(UCAT.ALICE)                                  -
      VOLUME(SMS001)                                    -
      CYLINDERS(50 10)                                  -
      ICFCATALOG                                        -
    )                                                    -
    DATA  ( CYLINDERS(45 10) )                          -
    INDEX ( CYLINDERS(5  2)  )

  DEFINE ALIAS                                          -
    ( NAME(ALICE)                                       -
      RELATE(UCAT.ALICE)                                -
    )

Output:

text
IDC0531I ENTRY UCAT.ALICE DEFINED
IDC0531I ENTRY ALICE DEFINED

After this, every dataset created under HLQ ALICE.* is catalogued in UCAT.ALICE automatically. Most users will never define a USERCATALOG or ALIAS directly — they are owned by the storage admin — but understanding the chain is essential for diagnosing "why does the catalog not find my dataset".

Return codes — LASTCC and MAXCC

Each command sets LASTCC (this command's RC) and updates MAXCC (the highest RC seen in the step). You can branch on either with IF.

text
  DELETE ALICE.MASTER.OLD.KSDS
  IF LASTCC <= 8 THEN -
    SET MAXCC = 0      /* swallow the not-found / already-deleted case */

  DEFINE CLUSTER ( NAME(ALICE.MASTER.OLD.KSDS) INDEXED KEYS(10 0) -
                   RECORDSIZE(80 80) RECORDS(100 50) ) -
                 DATA(NAME(ALICE.MASTER.OLD.KSDS.DATA)) -
                 INDEX(NAME(ALICE.MASTER.OLD.KSDS.INDEX))
  IF LASTCC NE 0 THEN -
    SET MAXCC = 16     /* force the step to fail loudly if define failed */

Output:

text
IDC0550I ENTRY (D) ALICE.MASTER.OLD.KSDS DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0
IDC0531I ENTRY ALICE.MASTER.OLD.KSDS DEFINED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

This "delete-then-define" pattern with SET MAXCC = 0 is the canonical idempotent allocate-or-recreate idiom. Without the SET, a not-found DELETE returns RC=8, which sets MAXCC=8, which propagates to the step return code.

RCMeaning
0Success
4Warning — minor issue, command succeeded
8Error — command failed (e.g. duplicate, not found)
12Serious — likely a syntax or logic error
16Terminal — environment problem (e.g. SYSIN open failure)

Common pitfalls

  1. Renaming a cluster without renaming its componentsALTER cluster NEWNAME doesn't touch DATA and INDEX. Always issue three ALTERs together.
  2. Forgetting BLDINDEX after DEFINE AIX — the alt-index is empty and UPGRADE only maintains it from then forward. Applications opening the path before BLDINDEX see no data.
  3. SHAREOPTIONS(3 3) everywhere — looks innocent and is the cause of many "the file is corrupt" calls. Batch programs without their own serialization will lose updates.
  4. Quoting matters in LEVEL vs ENTRIESLEVEL('ALICE.MASTER') matches everything under that HLQ; ENTRIES('ALICE.MASTER') looks for an entry literally named ALICE.MASTER. Mixing them returns zero entries.
  5. Deleting a GDG base without FORCE — fails if any generations exist. Use GDG FORCE or delete generations first.
  6. PURGE on an unexpired dataset — there's no undo, no recycle bin. RACF-controlled in production environments for exactly this reason.
  7. DEFINE CLUSTER with RECORDSIZE(80 80) but KEYS(10 5) — key extends past the record. IDCAMS detects this only when you load data; the define succeeds.
  8. Forgetting REUSE on a temporary cluster — without REUSE, the second time you open it for load mode IDCAMS rejects with "already loaded". REUSE re-clears it on open.
  9. No SYSPRINT in the JCL — IDCAMS opens with RC=16 and a JCL-error message. SYSPRINT is mandatory.
  10. Continuation hyphen in the wrong column — the - must be the last non-blank character on the line. A trailing space after the hyphen breaks continuation silently.
  11. LISTCAT ALL against a USERCATALOG with thousands of entries — generates megabytes of SYSOUT. Use NAMES first to scope, then ALL against specific entries.
  12. EXAMINE without ERRORLIMIT — defaults to 2,000,000,000 errors before it stops. On a truly broken cluster the SYSPRINT can be enormous. Set ERRORLIMIT(100) to be safe.

Sources

References consulted while writing this article. Links open in a new tab.

  • IBM Documentation — DFSMS Access Method Services Commands — Authoritative reference for IDCAMS commands (DEFINE, REPRO, LISTCAT, EXAMINE, BLDINDEX) covered in this article.

Real-world recipes

Define and load a KSDS from a flat file end-to-end

The full new-cluster bootstrap: define, load, define and build AIX, define path.

text
//ALICEJ01 JOB (ACCT),'ALICE',CLASS=A,MSGCLASS=X,NOTIFY=&SYSUID
//*
//* Step 1 — Clean slate (idempotent)
//*
//CLEAN    EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DELETE ALICE.MASTER.KSDS  CLUSTER
  IF LASTCC <= 8 THEN SET MAXCC = 0
/*
//*
//* Step 2 — Define cluster + AIX + path
//*
//DEFINE   EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DEFINE CLUSTER                                       -
    ( NAME(ALICE.MASTER.KSDS) INDEXED KEYS(10 0)       -
      RECORDSIZE(80 256) RECORDS(5000 500)             -
      FREESPACE(20 10) SHAREOPTIONS(2 3) )             -
    DATA  ( NAME(ALICE.MASTER.KSDS.DATA)  CISZ(4096) ) -
    INDEX ( NAME(ALICE.MASTER.KSDS.INDEX) CISZ(1024) )

  DEFINE AIX                                           -
    ( NAME(ALICE.MASTER.AIX.EMAIL)                     -
      RELATE(ALICE.MASTER.KSDS)                        -
      KEYS(40 10) RECORDSIZE(50 250)                   -
      RECORDS(5000 500) UPGRADE NONUNIQUEKEY )         -
    DATA  ( NAME(ALICE.MASTER.AIX.EMAIL.DATA)  )       -
    INDEX ( NAME(ALICE.MASTER.AIX.EMAIL.INDEX) )

  DEFINE PATH                                          -
    ( NAME(ALICE.MASTER.PATH.EMAIL)                    -
      PATHENTRY(ALICE.MASTER.AIX.EMAIL) UPDATE )
/*
//*
//* Step 3 — Load and build
//*
//LOAD     EXEC PGM=IDCAMS,COND=(0,NE)
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  REPRO INDATASET(ALICE.MASTER.FLAT)  -
        OUTDATASET(ALICE.MASTER.KSDS)

  BLDINDEX INDATASET(ALICE.MASTER.KSDS) -
           OUTDATASET(ALICE.MASTER.AIX.EMAIL)
/*

Output:

text
IDC0550I ENTRY (C) ALICE.MASTER.KSDS DELETED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0
IDC0531I ENTRY ALICE.MASTER.KSDS DEFINED
IDC0531I ENTRY ALICE.MASTER.AIX.EMAIL DEFINED
IDC0531I ENTRY ALICE.MASTER.PATH.EMAIL DEFINED
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0
IDC0005I NUMBER OF RECORDS PROCESSED WAS 5000
IDC01558I BLDINDEX COMPLETE, RECORDS PROCESSED = 5000
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

Daily backup and restore of a KSDS

Two short jobs: one unloads the KSDS to a flat file for archive, the other reloads it after a corruption.

text
//* BACKUP
//BACKUP   EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//KSDSIN   DD   DSN=ALICE.MASTER.KSDS,DISP=SHR
//FLATOUT  DD   DSN=ALICE.MASTER.BACKUP.FLAT(+1),
//              DISP=(NEW,CATLG,DELETE),
//              SPACE=(CYL,(10,5),RLSE),
//              DCB=(RECFM=VB,LRECL=260,BLKSIZE=27998)
//SYSIN    DD   *
  REPRO INFILE(KSDSIN) OUTFILE(FLATOUT)
/*

//* RESTORE
//RESTORE  EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  DELETE  ALICE.MASTER.KSDS CLUSTER
  IF LASTCC <= 8 THEN SET MAXCC = 0
  DEFINE CLUSTER -
    ( NAME(ALICE.MASTER.KSDS) INDEXED KEYS(10 0)         -
      RECORDSIZE(80 256) RECORDS(5000 500)               -
      FREESPACE(20 10) SHAREOPTIONS(2 3) )               -
    DATA  ( NAME(ALICE.MASTER.KSDS.DATA)  CISZ(4096) )   -
    INDEX ( NAME(ALICE.MASTER.KSDS.INDEX) CISZ(1024) )
  REPRO INDATASET(ALICE.MASTER.BACKUP.FLAT(0))           -
        OUTDATASET(ALICE.MASTER.KSDS)
/*

Output:

text
IDC0005I NUMBER OF RECORDS PROCESSED WAS 5000
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

The (+1) on the backup creates a new GDG generation each run; (0) on restore reads the current generation. Combined with a GDG LIMIT(14), you get free 14-day rolling backups.

Inspect why a job said "dataset not found"

The job referenced ALICE.MASTER.KSDS and got IGZ0035C. Find the actual cluster, its volume, and its catalog.

text
  LISTCAT ENTRIES('ALICE.MASTER.KSDS') ALL
  LISTCAT LEVEL('ALICE.MASTER') NAMES
  LISTCAT ALIAS LEVEL('ALICE')

Output:

text
LISTING FROM CATALOG -- ICFCAT.MASTER
NO ENTRY MATCHING ENTRIES NAME 'ALICE.MASTER.KSDS' WAS FOUND
ALIAS ----------- ALICE
       IN-CAT --- ICFCAT.MASTER
       ASSOCIATIONS
         USERCAT--UCAT.ALICE.OLD

The HLQ ALICE is aliased to a stale USERCATALOG — the cluster exists, but in a USERCATALOG that's no longer mounted to this system. Either remount UCAT or redefine the alias to the correct catalog.

Re-organize a fragmenting KSDS

Inserts are causing CI/CA splits and performance is degrading. Unload, redefine with bigger free space, reload.

text
//REORG    EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  REPRO INDATASET(ALICE.MASTER.KSDS)            -
        OUTDATASET(ALICE.MASTER.WORK.FLAT)      -
        REUSE

  DELETE ALICE.MASTER.KSDS CLUSTER

  DEFINE CLUSTER                                      -
    ( NAME(ALICE.MASTER.KSDS) INDEXED KEYS(10 0)      -
      RECORDSIZE(80 256) RECORDS(10000 1000)          -
      FREESPACE(30 20) SHAREOPTIONS(2 3) )            -
    DATA  ( NAME(ALICE.MASTER.KSDS.DATA)  CISZ(4096) )-
    INDEX ( NAME(ALICE.MASTER.KSDS.INDEX) CISZ(1024) )

  REPRO INDATASET(ALICE.MASTER.WORK.FLAT)        -
        OUTDATASET(ALICE.MASTER.KSDS)

  LISTCAT ENTRIES('ALICE.MASTER.KSDS') ALL
/*

Output:

text
IDC0005I NUMBER OF RECORDS PROCESSED WAS 5000
IDC0531I ENTRY ALICE.MASTER.KSDS DEFINED
IDC0005I NUMBER OF RECORDS PROCESSED WAS 5000
... cluster shows SPLITS-CI = 0, SPLITS-CA = 0

Doubled RECORDS and increased FREESPACE from 20/10 to 30/20 give the inserts room without hitting splits for the next quarter.

You don't know if the file even has data. Dump a few records in hex+character form.

text
  PRINT INDATASET(ALICE.MASTER.KSDS) DUMP COUNT(10)

Output:

text
KEY OF RECORD - F0F0F0F0F0F0F0F0F0F1
000000  F0F0F0F0 F0F0F0F0 F0F1C1D3 C9C3C540   *0000000001ALICE *
000010  C4C5E540 4040C140 40404040 40404040   *DEV    A         *
...
IDC0005I NUMBER OF RECORDS PROCESSED WAS 10

The hex side reveals byte-by-byte content; the character column on the right renders printable EBCDIC. Use this to confirm encoding, key alignment, and padding before suspecting a program bug.

Bulk-delete every test dataset under a HLQ

You're decommissioning a project. Drop every dataset under ALICE.TEST.* in one job.

text
  DELETE 'ALICE.TEST.*' MASK PURGE
  LISTCAT LEVEL('ALICE.TEST') NAMES

Output:

text
IDC0550I ENTRY (C) ALICE.TEST.KSDS1 DELETED
IDC0550I ENTRY (C) ALICE.TEST.KSDS2 DELETED
IDC0550I ENTRY (A) ALICE.TEST.SEQ1  DELETED
IDC0531I NO ENTRIES MEET SEARCH CRITERIA
IDC0001I FUNCTION COMPLETED, HIGHEST CONDITION CODE WAS 0

MASK enables wildcards; PURGE ignores expiration dates. In production, run with NOSCRATCH first to uncatalog only — verify nothing important got matched — then a second pass to scratch.

Compare cluster statistics before and after a load

A diagnostic for tracking insert behavior over time.

text
//STATS    EXEC PGM=IDCAMS
//SYSPRINT DD   SYSOUT=*
//SYSIN    DD   *
  LISTCAT ENTRIES('ALICE.MASTER.KSDS.DATA') ALL
/*

Output:

text
STATISTICS
  REC-TOTAL------------5234       SPLITS-CI--------------12
  REC-DELETED------------0       SPLITS-CA-------------- 1
  REC-INSERTED---------234       FREESPACE-%CI-------17
  REC-UPDATED-----------54       FREESPACE-%CA-------09

12 CI splits and 1 CA split since the last reorg — still well within the budget. When SPLITS-CI climbs into the thousands or FREESPACE-%CI drops near zero, schedule a reorg.

Run IDCAMS interactively from TSO READY

For ad-hoc one-liners you don't need JCL — invoke IDCAMS as a TSO command.

text
READY
TSO IDCAMS
ENTER COMMAND>
  LISTCAT ENTRIES('ALICE.MASTER.KSDS') NAMES
LISTING FROM CATALOG -- ICFCAT.MASTER
CLUSTER ------- ALICE.MASTER.KSDS
DATA --------- ALICE.MASTER.KSDS.DATA
INDEX --------- ALICE.MASTER.KSDS.INDEX
ENTER COMMAND>
  END

READY

Output: (LISTCAT result then back to TSO READY)

Two commands per line at most — TSO's input width is 80 columns and IDCAMS truncates silently past that. For anything more than a LISTCAT or a quick DELETE, write JCL.