1. SD — o arquivo de trabalho do SORT

Assim como arquivos comuns usam FD, o arquivo de trabalho do SORT usa SD (Sort Description). Ele declara o layout do registro que será ordenado e é referenciado pelos verbos RELEASE e RETURN:

COBOL Declarando o arquivo de trabalho do SORT
       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT ARQ-ENTRADA  ASSIGN TO DDENTRAD
               ORGANIZATION IS SEQUENTIAL.
           SELECT ARQ-SAIDA    ASSIGN TO DDSAIDA
               ORGANIZATION IS SEQUENTIAL.

             * Arquivo de trabalho: ASSIGN TO deve bater com DD no JCL
             * ou usar SORTWK01 (DD gerada automaticamente pelo sistema)
           SELECT ARQ-SORT     ASSIGN TO SORTWK01.

       DATA DIVISION.
       FILE SECTION.
       FD  ARQ-ENTRADA.
       01  REG-ENTRADA.
           05  EN-CPF       PIC X(11).
           05  EN-DATA      PIC 9(08).
           05  EN-VALOR     PIC S9(13)V99.
           05  EN-TIPO      PIC X(01).
           05  EN-FILLER    PIC X(25).

             * SD no lugar de FD para o arquivo de ordenação
       SD  ARQ-SORT.
       01  REG-SORT.
           05  SK-CPF       PIC X(11).   *chave de ordenação
           05  SK-DATA      PIC 9(08).   *chave de ordenação
           05  SK-VALOR     PIC S9(13)V99.
           05  SK-TIPO      PIC X(01).
           05  SK-FILLER    PIC X(25).

💗 Para iniciantes — SD vs FD

  • FD declara um arquivo real (de entrada ou saída) que você abre e fecha explicitamente com OPEN/CLOSE
  • SD declara o arquivo de trabalho temporário que o SORT usa internamente — você nunca abre ou fecha com OPEN/CLOSE; o verbo SORT gerencia isso
  • O layout do SD não precisa ser idêntico ao do FD, mas o tamanho do registro deve ser o mesmo

2. SORT com USING e GIVING

A forma mais simples: lê o arquivo de entrada (USING), ordena pelas chaves especificadas e grava no arquivo de saída (GIVING). Não há lógica de filtragem ou processamento intermediário:

COBOL SORT com USING e GIVING
       PROCEDURE DIVISION.
       0000-INICIO.
             * Ordena ARQ-ENTRADA por CPF crescente e data crescente
             * e grava resultado em ARQ-SAIDA
           SORT ARQ-SORT
               ON ASCENDING KEY  SK-CPF
               ON ASCENDING KEY  SK-DATA
               USING  ARQ-ENTRADA
               GIVING ARQ-SAIDA
           STOP RUN.

             * Ordem descendente em uma das chaves
           SORT ARQ-SORT
               ON ASCENDING KEY  SK-CPF
               ON DESCENDING KEY SK-DATA   *data mais recente primeiro
               USING  ARQ-ENTRADA
               GIVING ARQ-SAIDA

             * Múltiplos arquivos de entrada (mesma estrutura)
           SORT ARQ-SORT
               ON ASCENDING KEY  SK-CPF
               USING  ARQ-JANEIRO
                      ARQ-FEVEREIRO
                      ARQ-MARCO
               GIVING ARQ-SAIDA

✅ USING/GIVING abre e fecha os arquivos automaticamente

Com USING e GIVING, o COBOL abre os arquivos antes de ordenar e os fecha ao terminar. Não chame OPEN nem CLOSE para esses arquivos antes ou depois do SORT — você receberá um erro de arquivo já aberto. Se precisar processar os dados antes ou depois da ordenação, use INPUT PROCEDURE e OUTPUT PROCEDURE.

3. SORT com INPUT PROCEDURE

Quando você precisa filtrar ou transformar os registros antes de ordená-los, substitua o USING por INPUT PROCEDURE. Sua procedure lê o arquivo de entrada, processa cada registro e usa RELEASE para enviá-lo ao sort:

COBOL SORT com INPUT PROCEDURE — filtragem antes da ordenação
       PROCEDURE DIVISION.
       0000-INICIO.
           OPEN INPUT ARQ-ENTRADA

           SORT ARQ-SORT
               ON ASCENDING KEY SK-CPF
                                 SK-DATA
               INPUT PROCEDURE IS  1000-FILTRA-ENTRADA
               GIVING              ARQ-SAIDA

           CLOSE ARQ-ENTRADA
           STOP RUN.

             * INPUT PROCEDURE: lê a entrada e passa apenas o que interessa
       1000-FILTRA-ENTRADA.
           MOVE 'N' TO WS-FIM
           READ ARQ-ENTRADA
               AT END SET FIM-ARQUIVO TO TRUE
           END-READ
           PERFORM UNTIL FIM-ARQUIVO
                     * Filtra: envia ao sort apenas tipo 'C' (crédito)
               IF EN-TIPO = 'C'
                   MOVE EN-CPF   TO SK-CPF
                   MOVE EN-DATA  TO SK-DATA
                   MOVE EN-VALOR TO SK-VALOR
                   MOVE EN-TIPO  TO SK-TIPO
                   RELEASE REG-SORT      *envia para o sort
               END-IF
               READ ARQ-ENTRADA
                   AT END SET FIM-ARQUIVO TO TRUE
               END-READ
           END-PERFORM.

             * RELEASE FROM: preenche o REG-SORT e envia em um passo
             * (quando o layout de entrada e o SD são idênticos)
                   RELEASE REG-SORT FROM REG-ENTRADA

🦕 Analogia — RELEASE é como colocar na fila

Imagine o SORT como um funcionário que organiza fichas em ordem. A INPUT PROCEDURE é você selecionando quais fichas entregar. O RELEASE é o ato de entregar cada ficha para ele. Depois que você termina de entregar (a procedure retorna), ele ordena tudo e grava no arquivo de saída.

4. SORT com OUTPUT PROCEDURE

Quando você precisa processar ou transformar os registros já ordenados antes de gravar, substitua o GIVING por OUTPUT PROCEDURE. Sua procedure usa RETURN para buscar cada registro do sort já em ordem:

COBOL SORT com OUTPUT PROCEDURE — processamento após ordenação
       PROCEDURE DIVISION.
       0000-INICIO.
           OPEN OUTPUT ARQ-SAIDA

           SORT ARQ-SORT
               ON ASCENDING KEY SK-CPF
               USING               ARQ-ENTRADA
               OUTPUT PROCEDURE IS 2000-PROCESSA-ORDENADO

           CLOSE ARQ-SAIDA
           STOP RUN.

             * OUTPUT PROCEDURE: consome o sort já ordenado
       2000-PROCESSA-ORDENADO.
           MOVE 'N'   TO WS-FIM
           MOVE SPACES TO WS-CPF-ANTERIOR
           MOVE ZEROS  TO WS-TOTAL-CPF

           RETURN ARQ-SORT         *busca primeiro registro ordenado
               AT END SET FIM-ARQUIVO TO TRUE
           END-RETURN

           PERFORM UNTIL FIM-ARQUIVO
                     * Detecta quebra de grupo (change of CPF)
               IF SK-CPF = WS-CPF-ANTERIOR
                   ADD SK-VALOR TO WS-TOTAL-CPF
               ELSE
                   IF WS-CPF-ANTERIOR NOT = SPACES
                       PERFORM 2100-GRAVA-TOTAL
                   END-IF
                   MOVE SK-CPF  TO WS-CPF-ANTERIOR
                   MOVE SK-VALOR TO WS-TOTAL-CPF
               END-IF
               RETURN ARQ-SORT
                   AT END SET FIM-ARQUIVO TO TRUE
               END-RETURN
           END-PERFORM
           IF WS-CPF-ANTERIOR NOT = SPACES
               PERFORM 2100-GRAVA-TOTAL
           END-IF.

       2100-GRAVA-TOTAL.
           MOVE WS-CPF-ANTERIOR TO SA-CPF
           MOVE WS-TOTAL-CPF    TO SA-TOTAL
           WRITE REG-SAIDA FROM WS-LINHA-SAIDA.

5. SORT com INPUT e OUTPUT PROCEDURE

Você pode combinar as duas procedures no mesmo SORT — filtra na entrada, ordena, processa na saída:

COBOL SORT com INPUT e OUTPUT PROCEDURE
       PROCEDURE DIVISION.
       0000-INICIO.
           OPEN INPUT  ARQ-ENTRADA
                OUTPUT ARQ-SAIDA

           SORT ARQ-SORT
               ON ASCENDING KEY SK-CPF
                                 SK-DATA
               INPUT PROCEDURE IS  1000-FILTRA-ENTRADA
               OUTPUT PROCEDURE IS 2000-PROCESSA-SAIDA

           CLOSE ARQ-ENTRADA
                 ARQ-SAIDA
           STOP RUN.
FormaEntradaSaídaQuando usar
USING / GIVINGAutomáticaAutomáticaOrdenação simples sem processamento
INPUT PROC / GIVINGManual (RELEASE)AutomáticaFiltrar/transformar antes de ordenar
USING / OUTPUT PROCAutomáticaManual (RETURN)Processar/acumular após ordenar
INPUT PROC / OUTPUT PROCManual (RELEASE)Manual (RETURN)Filtro na entrada e processamento na saída

6. MERGE — mesclando arquivos ordenados

O MERGE combina dois ou mais arquivos que já estão ordenados pelas mesmas chaves, produzindo um único arquivo ordenado. É mais eficiente do que reunir os arquivos e ordenar novamente:

COBOL MERGE — combinando arquivos já ordenados
       ENVIRONMENT DIVISION.
       FILE-CONTROL.
           SELECT ARQ-JAN  ASSIGN TO DDJAN
               ORGANIZATION IS SEQUENTIAL.
           SELECT ARQ-FEV  ASSIGN TO DDFEV
               ORGANIZATION IS SEQUENTIAL.
           SELECT ARQ-MAR  ASSIGN TO DDMAR
               ORGANIZATION IS SEQUENTIAL.
           SELECT ARQ-TRIM ASSIGN TO DDTRIM
               ORGANIZATION IS SEQUENTIAL.
           SELECT ARQ-MERGE ASSIGN TO SORTMRG1.

       DATA DIVISION.
       FILE SECTION.
             * FDs para os três arquivos de entrada e o de saída...
       SD  ARQ-MERGE.
       01  REG-MERGE.
           05  MG-CPF    PIC X(11).
           05  MG-DATA   PIC 9(08).
           05  MG-RESTO  PIC X(39).

       PROCEDURE DIVISION.
       0000-INICIO.
             * Os três arquivos devem estar ordenados por CPF e DATA
           MERGE ARQ-MERGE
               ON ASCENDING KEY MG-CPF
                                 MG-DATA
               USING  ARQ-JAN
                      ARQ-FEV
                      ARQ-MAR
               GIVING ARQ-TRIM
           STOP RUN.

             * MERGE também aceita OUTPUT PROCEDURE
           MERGE ARQ-MERGE
               ON ASCENDING KEY MG-CPF
               USING               ARQ-JAN ARQ-FEV ARQ-MAR
               OUTPUT PROCEDURE IS 2000-PROCESSA-MERGE

⚠️ MERGE não tem INPUT PROCEDURE

Diferente do SORT, o MERGE não aceita INPUT PROCEDURE. Os arquivos de entrada devem estar todos corretamente ordenados pelas mesmas chaves antes de serem passados ao MERGE. Se precisar filtrar ou transformar a entrada, use um SORT com INPUT PROCEDURE antes de chamar o MERGE, ou use o SORT com múltiplos arquivos no USING.

7. SORT COBOL vs DFSORT no JCL

Em produção, a maioria das ordenações simples é feita pelo utilitário DFSORT (ou SYNCSORT) diretamente no JCL, sem passar por um programa COBOL. Quando usar cada abordagem:

JCL DFSORT no JCL — ordenação simples sem COBOL
       //SORTSTEP EXEC PGM=SORT
       //SYSOUT   DD SYSOUT=*
       //SORTIN   DD DSN=PROD.MOVIMENTO.DIARIO,DISP=SHR
       //SORTOUT  DD DSN=PROD.MOVIMENTO.ORDENADO,
       //            DISP=(NEW,CATLG,DELETE),
       //            SPACE=(CYL,(5,2)),RECFM=FB,LRECL=60
       //SYSIN    DD *
         SORT FIELDS=(1,11,CH,A,   <- CPF posição 1 tamanho 11, alfanum, ascend
                      12,8,CH,A)   <- DATA posição 12 tamanho 8, alfanum, ascend
         INCLUDE COND=(20,1,CH,EQ,C'C')   <- filtra só tipo 'C'
       /*
SORT no COBOLDFSORT no JCL
Lógica complexa✅ Permite código COBOL completo❌ Limitado às opções do utilitário
Filtros simplesPossível com INPUT PROC✅ INCLUDE/OMIT muito mais simples
PerformanceBoa✅ Melhor — otimizado para hardware
ManutençãoRequer recompilação✅ Altera só o JCL
Transformação de dados✅ Total via OUTPUT PROCEDURELimitada a operações básicas
Quando usarQuando há lógica de negócio integradaPara ordenações e filtros simples

🟣 Para quem já programa — SORT COBOL chama DFSORT internamente

No IBM z/OS, quando você executa o verbo SORT do COBOL, ele chama o DFSORT (ou SYNCSORT, dependendo do instalado) por baixo dos panos. O pré-processador de sort transforma as DDs do JCL automaticamente. Por isso o performance é comparável — você não perde nada usando o verbo COBOL. A diferença real está na flexibilidade: com INPUT/OUTPUT PROCEDURE você tem o poder total do COBOL para filtrar e processar.

8. Exemplo completo

Um programa que lê um arquivo de movimentos, filtra apenas os débitos acima de R$1.000, ordena por CPF e data, e gera um relatório com total por cliente:

COBOL Programa completo — RELDEBITO
       IDENTIFICATION DIVISION.
       PROGRAM-ID. RELDEBITO.

       ENVIRONMENT DIVISION.
       INPUT-OUTPUT SECTION.
       FILE-CONTROL.
           SELECT ARQ-MOVIMENTO ASSIGN TO DDMOVTO
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-FS-MOV.
           SELECT ARQ-RELATORIO ASSIGN TO DDRELAT
               ORGANIZATION IS SEQUENTIAL
               FILE STATUS IS WS-FS-REL.
           SELECT ARQ-WORKSORT ASSIGN TO SORTWK01.

       DATA DIVISION.
       FILE SECTION.
       FD  ARQ-MOVIMENTO.
       01  REG-MOVIMENTO.
           05  MV-CPF       PIC X(11).
           05  MV-DATA      PIC 9(08).
           05  MV-TIPO      PIC X(01).
               88  MV-DEBITO   VALUE 'D'.
           05  MV-VALOR     PIC S9(11)V99.
           05  MV-FILLER    PIC X(26).

       FD  ARQ-RELATORIO.
       01  REG-RELATORIO  PIC X(80).

       SD  ARQ-WORKSORT.
       01  REG-WORKSORT.
           05  WK-CPF       PIC X(11).
           05  WK-DATA      PIC 9(08).
           05  WK-TIPO      PIC X(01).
           05  WK-VALOR     PIC S9(11)V99.
           05  WK-FILLER    PIC X(26).

       WORKING-STORAGE SECTION.
       01  WS-FS-MOV        PIC X(02).
       01  WS-FS-REL        PIC X(02).
       01  WS-FIM-ENT       PIC X(01).
           88  FIM-ENTRADA   VALUE 'S'.
       01  WS-FIM-SORT      PIC X(01).
           88  FIM-SORT      VALUE 'S'.
       01  WS-CPF-ANT       PIC X(11).
       01  WS-TOTAL-CLI     PIC S9(11)V99.
       01  WS-LIMITE        PIC S9(11)V99
                            VALUE 1000.00.
       01  WS-LINHA         PIC X(80).

       PROCEDURE DIVISION.
       0000-INICIO.
           OPEN INPUT  ARQ-MOVIMENTO
                OUTPUT ARQ-RELATORIO

           SORT ARQ-WORKSORT
               ON ASCENDING KEY  WK-CPF
               ON ASCENDING KEY  WK-DATA
               INPUT PROCEDURE IS  1000-SELECIONA
               OUTPUT PROCEDURE IS 2000-RELATORIO

           CLOSE ARQ-MOVIMENTO
                 ARQ-RELATORIO
           STOP RUN.

       1000-SELECIONA.
           MOVE 'N' TO WS-FIM-ENT
           READ ARQ-MOVIMENTO
               AT END SET FIM-ENTRADA TO TRUE
           END-READ
           PERFORM UNTIL FIM-ENTRADA
               IF MV-DEBITO AND
                  MV-VALOR >= WS-LIMITE
                   RELEASE REG-WORKSORT FROM REG-MOVIMENTO
               END-IF
               READ ARQ-MOVIMENTO
                   AT END SET FIM-ENTRADA TO TRUE
               END-READ
           END-PERFORM.

       2000-RELATORIO.
           MOVE 'N'    TO WS-FIM-SORT
           MOVE SPACES TO WS-CPF-ANT
           MOVE ZEROS  TO WS-TOTAL-CLI

           RETURN ARQ-WORKSORT
               AT END SET FIM-SORT TO TRUE
           END-RETURN

           PERFORM UNTIL FIM-SORT
               IF WK-CPF NOT = WS-CPF-ANT
                   IF WS-CPF-ANT NOT = SPACES
                       PERFORM 2100-IMPRIME-TOTAL
                   END-IF
                   MOVE WK-CPF  TO WS-CPF-ANT
                   MOVE ZEROS   TO WS-TOTAL-CLI
               END-IF
               ADD WK-VALOR TO WS-TOTAL-CLI
               RETURN ARQ-WORKSORT
                   AT END SET FIM-SORT TO TRUE
               END-RETURN
           END-PERFORM
           IF WS-CPF-ANT NOT = SPACES
               PERFORM 2100-IMPRIME-TOTAL
           END-IF.

       2100-IMPRIME-TOTAL.
           STRING WS-CPF-ANT   DELIMITED SIZE
                  '  TOTAL: '   DELIMITED SIZE
                  WS-TOTAL-CLI DELIMITED SIZE
               INTO WS-LINHA
           END-STRING
           WRITE REG-RELATORIO FROM WS-LINHA.

9. Erros comuns

1. OPEN/CLOSE nos arquivos de USING/GIVING

COBOL Não abra/feche arquivos gerenciados pelo SORT
             * ERRADO: SORT com USING/GIVING gerencia OPEN e CLOSE
           OPEN INPUT ARQ-ENTRADA    *erro: já vai ser aberto pelo SORT
           SORT ARQ-SORT
               ON ASCENDING KEY SK-CPF
               USING  ARQ-ENTRADA
               GIVING ARQ-SAIDA

             * CORRETO: não abra/feche quando usar USING/GIVING
           SORT ARQ-SORT
               ON ASCENDING KEY SK-CPF
               USING  ARQ-ENTRADA
               GIVING ARQ-SAIDA

             * Com INPUT/OUTPUT PROCEDURE: você abre e fecha manualmente
           OPEN INPUT  ARQ-ENTRADA
                OUTPUT ARQ-SAIDA
           SORT ARQ-SORT ...
               INPUT PROCEDURE IS  1000-ENTRADA
               OUTPUT PROCEDURE IS 2000-SAIDA
           CLOSE ARQ-ENTRADA ARQ-SAIDA

2. GO TO de dentro da INPUT/OUTPUT PROCEDURE

COBOL Não saia da procedure com GO TO externo
             * ERRADO: transferir controle para fora da INPUT/OUTPUT PROCEDURE
             * com GO TO causa comportamento indefinido
       1000-FILTRA-ENTRADA.
           READ ARQ-ENTRADA
               AT END
                   GO TO 9000-TRATA-ERRO   *PERIGOSO: fora da procedure
           END-READ.

             * CORRETO: trate erros dentro da própria procedure
       1000-FILTRA-ENTRADA.
           READ ARQ-ENTRADA
               AT END SET FIM-ENTRADA TO TRUE
           END-READ
           IF WS-FS-MOV NOT = '00' AND
              WS-FS-MOV NOT = '10'
               MOVE 'S' TO WS-ERRO-SORT
               SET FIM-ENTRADA TO TRUE  *aborta a procedure
           END-IF.

3. Chave de SORT com tipo numérico em campo alfanumérico

COBOL Tipo da chave importa — alfanumérico vs numérico
             * Ordenar valor numérico declarado como X ordena por string
             * '10' vem antes de '9' em ordenação alfanumérica (compare '1' vs '9')
       SD  ARQ-SORT.
       01  REG-SORT.
           05  SK-VALOR   PIC X(13).  *ERRADO para ordenar numericamente

             * CORRETO: declare a chave com o tipo real
       01  REG-SORT.
           05  SK-VALOR   PIC S9(11)V99.  *correto: numérico ordenado por valor

🟣 Para quem já programa — SORT ON EXCEPTION e RETURN-CODE

O verbo SORT não tem cláusula ON EXCEPTION como o CALL. Para detectar falha na ordenação, verifique o RETURN-CODE logo após o SORT: código 0 é sucesso, 16 indica erro grave no sort (espaço insuficiente, arquivo inacessível etc.). Também defina SORT-RETURN em Working Storage como PIC S9(4) COMP — ao usar SORT no COBOL, o runtime preenche esse campo especial automaticamente.