1. DSN — nome do dataset

DSN (ou DSNAME) especifica o nome do dataset a ser acessado. Os nomes seguem a convenção HLQ.segmento2.segmento3..., onde HLQ é o High-Level Qualifier (geralmente o userid ou nome da aplicação).

JCLDSN — exemplos de nomenclatura
* Dataset simples
//DD01  DD  DSN=PROD.FUNC.DADOS,DISP=SHR

* Membro de PDS (Partitioned Dataset)
//DD02  DD  DSN=PROD.COBSRC(CALCFOL),DISP=SHR

* Dataset temporario (sobrevive apenas no job)
//DD03  DD  DSN=&&TEMP,DISP=(NEW,PASS),
//            UNIT=SYSDA,SPACE=(TRK,(5,2))

💗 Convenção de nomes de datasets

Cada instalação tem suas convenções, mas o padrão mais comum é:
AMBIENTE.APLICACAO.TIPO.SUFIXO

Exemplos:
PROD.FOLHA.FUNC.MENSAL — produção, folha, funcionários, mensal
TEST.FOLHA.FUNC.202412 — teste, folha, funcionários, dezembro 2024
LC001.COBOL.SOURCE — userid LC001, fonte COBOL

Cada segmento tem no máximo 8 caracteres e o nome total não pode ultrapassar 44 caracteres.

2. DISP — status e disposição

O parâmetro DISP é o mais importante do DD. Ele tem até 3 subparâmetros:

JCLSintaxe do DISP
DISP=(status,acao-normal,acao-abend)

1º subparâmetro — status (estado atual do dataset)

ValorSignificado
NEWO dataset não existe — será criado agora
OLDExiste, abre com acesso exclusivo (ninguém mais pode usar)
SHRExiste, abre compartilhado (vários jobs podem ler ao mesmo tempo)
MODExiste (ou cria se não existir), posiciona no final para adicionar registros

2º subparâmetro — ação normal (quando o step termina com sucesso)

ValorSignificado
KEEPMantém o dataset, mas não o cataloga
CATLGMantém e cataloga (registra no catálogo para uso futuro)
DELETEApaga o dataset
PASSPassa o dataset para o próximo step do mesmo job
UNCATLGMantém o dataset mas remove do catálogo

3º subparâmetro — ação em caso de abend

Opcional. Se omitido, usa o mesmo valor do 2º subparâmetro. Mais comum é usar DELETE para limpar datasets parcialmente criados em caso de falha.

JCLDISP — os casos mais comuns
* Arquivo de entrada ja existente (leitura)
//ENTRADA  DD  DSN=PROD.FUNC.DADOS,DISP=SHR

* Criar novo dataset e catalogar (se ok) ou apagar (se erro)
//SAIDA    DD  DSN=PROD.RELAT.OUT,
//              DISP=(NEW,CATLG,DELETE),
//              UNIT=SYSDA,SPACE=(TRK,(10,5))

* Dataset temporario: passa para proximo step
//TEMP01   DD  DSN=&&WORK,DISP=(NEW,PASS),
//              UNIT=SYSDA,SPACE=(CYL,(1,1))

* No step seguinte, recebe o dataset temporario
//TEMP02   DD  DSN=&&WORK,DISP=(OLD,DELETE)

* Adicionar registros ao final de um arquivo existente
//LOG      DD  DSN=PROD.LOG.ERROS,DISP=MOD

🦕 Analogia — DISP é como um formulário de contrato de locação

Você aluga um apartamento (dataset). O formulário diz:
Estado atual: "novo" (acabou de ser construído) ou "existente" (alguém já morou)
O que fazer quando você sair: "deixar para o próximo inquilino" (KEEP) ou "demolir" (DELETE) ou "registrar no cartório" (CATLG)
O que fazer se der problema: "demolir e limpar o terreno" (DELETE no 3º subparâmetro)

3. UNIT — dispositivo de armazenamento

Define em qual tipo de dispositivo o dataset será criado. Necessário apenas para datasets novos (DISP=NEW).

ValorSignificado
SYSDAQualquer dispositivo DASD (disco) disponível — o mais usado
TAPEFita magnética
3390Tipo específico de disco IBM 3390
VIODataset temporário em memória virtual (muito rápido)

4. SPACE — alocação de espaço

Define quanto espaço em disco reservar para um novo dataset. Errar o SPACE causa dois problemas clássicos: alocar de menos (dataset extende até o limite e o job falha com B37) ou alocar de mais (desperdício de disco).

JCLSintaxe do SPACE
SPACE=(unidade,(primario,secundario)[,RLSE])

* Exemplos:
* 10 trilhas primárias, 5 secundárias
SPACE=(TRK,(10,5))

* 2 cilindros primários, 1 secundário
SPACE=(CYL,(2,1))

* 80 blocos primários, 20 secundários, libera espaço nao usado (RLSE)
SPACE=(80,(80,20),RLSE)
UnidadeO que éQuando usar
TRKTrilhas de disco (menor unidade)Datasets pequenos (até alguns MB)
CYLCilindros (15 trilhas cada)Datasets médios a grandes
númeroTamanho de bloco em bytesQuando você sabe o tamanho exato dos registros

✅ RLSE — libere o espaço não usado

Adicionar RLSE ao final do SPACE instrui o sistema a devolver ao pool de disco qualquer espaço primário que não foi utilizado ao fechar o dataset. É uma boa prática sempre adicionar RLSE em datasets de saída, especialmente quando você não sabe exatamente quanto espaço vai precisar.

⚠️ Abend B37 — dataset cheio

Quando um dataset atinge o limite de espaço alocado (primário + todas as extensões secundárias), o job falha com o abend B37. Isso significa que você alocou pouco espaço. Solução: aumente o valor primário do SPACE ou adicione mais extensões secundárias. Cada dataset pode ter no máximo 16 extensões secundárias além do primário.

5. DCB — características do dataset

O DCB (Data Control Block) define o formato físico dos registros. Frequentemente pode ser omitido quando o dataset já existe ou quando o programa define isso internamente.

SubparâmetroSignificadoValores comuns
DSORGOrganização do datasetPS (sequencial), PO (particionado)
RECFMFormato dos registrosFB (fixo bloqueado), VB (variável bloqueado), F, V, U
LRECLTamanho de cada registro em bytes80, 133, 200, etc.
BLKSIZETamanho do bloco físicoMúltiplo do LRECL; use 0 para o sistema calcular
JCLDCB na prática
* Dataset sequencial de registros fixos, 100 bytes cada
//SAIDA  DD  DSN=PROD.OUT.DADOS,
//            DISP=(NEW,CATLG,DELETE),
//            UNIT=SYSDA,SPACE=(CYL,(5,2),RLSE),
//            DCB=(DSORG=PS,RECFM=FB,LRECL=100,BLKSIZE=0)
*                                                    ^--- sistema calcula

💗 RECFM=FB — o mais comum

FB = Fixed Blocked (fixo bloqueado). É o formato mais eficiente e comum em mainframe:
Fixed = todos os registros têm o mesmo tamanho (LRECL)
Blocked = vários registros são agrupados num mesmo bloco físico de disco, economizando espaço e I/O

No seu programa COBOL, o campo FD deve declarar RECORD CONTAINS n CHARACTERS com o mesmo valor do LRECL.

6. SYSOUT — saída para impressora/spool

SYSOUT envia a saída diretamente para o spool do JES (onde você vê pelo SDSF) ou para uma impressora, sem criar um dataset permanente.

JCLSYSOUT — variações
* Envia para o spool (visualizar no SDSF)
//RELAT    DD  SYSOUT=*

* Envia para impressora classe A
//RELAT    DD  SYSOUT=A

* Descarta a saida (equivalente a /dev/null no Linux)
//RELAT    DD  SYSOUT=*,OUTLIM=0

7. LIKE — herdar características

O parâmetro LIKE é um atalho moderno: o novo dataset herda RECFM, LRECL, BLKSIZE e DSORG de um dataset existente. Elimina a necessidade de repetir o DCB.

JCLLIKE — herdar DCB de outro dataset
* Sem LIKE — verboso
//SAIDA  DD  DSN=PROD.OUT.NOV,DISP=(NEW,CATLG,DELETE),
//            UNIT=SYSDA,SPACE=(CYL,(5,2)),
//            DCB=(DSORG=PS,RECFM=FB,LRECL=200,BLKSIZE=0)

* Com LIKE — herda DCB do dataset de entrada
//SAIDA  DD  DSN=PROD.OUT.NOV,DISP=(NEW,CATLG,DELETE),
//            UNIT=SYSDA,SPACE=(CYL,(5,2)),
//            LIKE=PROD.FUNC.DADOS

8. Receitas prontas para copiar

Ler arquivo existente

JCLLeitura
//LEITURA  DD  DSN=PROD.FUNC.DADOS,DISP=SHR

Criar arquivo novo e catalogar

JCLCriação
//SAIDA    DD  DSN=PROD.OUT.DADOS,
//              DISP=(NEW,CATLG,DELETE),
//              UNIT=SYSDA,
//              SPACE=(CYL,(5,2),RLSE),
//              DCB=(DSORG=PS,RECFM=FB,LRECL=100,BLKSIZE=0)

Relatório para o spool

JCLSpool
//RELAT    DD  SYSOUT=*

Dataset temporário entre steps

JCLPassagem entre steps
* Step 1: cria e passa
//TEMP     DD  DSN=&&INTER,DISP=(NEW,PASS),
//              UNIT=SYSDA,SPACE=(TRK,(10,5)),
//              DCB=(RECFM=FB,LRECL=100)

* Step 2: recebe e deleta ao final
//TEMP     DD  DSN=&&INTER,DISP=(OLD,DELETE)

🟣 BLKSIZE=0 — deixe o sistema calcular

Antigamente era obrigatório calcular o BLKSIZE manualmente para otimizar o uso de disco. Hoje, especificar BLKSIZE=0 instrui o sistema a calcular automaticamente o tamanho de bloco ótimo para o dispositivo. Use sempre BLKSIZE=0 em código novo — o sistema faz melhor do que a maioria das estimativas manuais.