Mostrando entradas con la etiqueta Alvarito. Mostrar todas las entradas
Mostrando entradas con la etiqueta Alvarito. Mostrar todas las entradas

lunes, 28 de diciembre de 2020

SORT vol.3: OUTFIL.

ACTUALIZADO: ejemplo de STARTREC/ENDREC

La estructura general de un SORT es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2(opcional),DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  …
  …

PGM=SORT --> Indica el programa a utilizar, en este caso el SORT.
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:


OUTFIL

Esta utilidad nos permite, a partir de un fichero(o varios) de entrada, filtrar en varios ficheros de salida.
Además, permite utilizar simultáneamente, todos las utilidades del SORT(OUTREC, INCLUDE, etc.) para filtrar cada fichero independientemente del otro.

NOTA: En este documento no vamos a entrar a explicar el OUTREC, INCLUDE, etc. Existen artículos en este blog que explican en detalle estas utilidades.

La definición de un OUTFIL es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SALIDA1  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SALIDA2  DD DSN=nombre.fichero.salida2,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SALIDA3  DD DSN=nombre.fichero.salida3,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 OUTFIL FNAMES=SALIDA1,INCLUDE=(…),
                        OUTREC=(…) ,
                         INREC=(…) ,
                         …
 OUTFIL FNAMES=SALIDA2,INCLUDE=(…),
                        OUTREC=(…) ,
                         INREC=(…) ,
                         …
 OUTFIL FNAMES=SALIDA3,SAVE


Primero se han de definir los ficheros de salida, asignando un nombre a cada uno (SALIDA1, SALIDA2, SALIDA3, etc..)
Luego, por cada fichero de salida se introduce un OUTFIL, y en el FNAMES se asocia con el nombre asignado antes (ejemplo FNAMES=SALIDA1).
A continuación, indicar en cada fichero, el filtro que se va a utilizar mediante INCLUDE, OUTREC, etc…
Utilizando la opción SAVE, se indica que todos los registros que no cumplan ninguna de las condiciones anteriores se escribirán en el fichero indicado. En el caso del ejemplo en la SALIDA3.

Cosas a tener en cuenta:
- Cuidado al escribir el INCLUDE, OUTREC, etc. Normalmente se escribe "INCLUDE COND=", y sin embargo, en el OUTFIL se escribe "INCLUDE=". Lo mismo pasa con el "OUTREC FIELDS=", que pasa a ser "OUTREC=". Por norma general, se ha de quitar la segunda parte. El "OMIT COND=" quedaría "OMIT=", etc.

Vamos a ver un ejemplo:

Situación 1. Vamos a dividir el siguiente fichero en 2, filtrando por la Situación Laboral. En el fichero de salida 1 meteremos los Asalariados y en el fichero de salida 2 los autónomos. Además en cada fichero, vamos a sacar únicamente el Nombre y los Apellidos:


----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO
000000006ANTONIO   VILLA     SUSO     AUTONOMO  
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO  
000000001JOSE      LOPEZ     PITA     AUTONOMO  
000000004CARLOS    POLO      DEL BARROAUTONOMO  
000000003CARLOS    PEREZ     FANO     AUTONOMO  


La fórmula sería:

//OUTREC   EXEC SORTD
//SYSOUT   DD SYSOUT=*
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//SALIDA1  DD DSN=nombre.fichero.asalariados,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SALIDA2  DD DSN=nombre.fichero.autónomos,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSIN    DD *
SORT FIELDS=COPY
OUTFIL FNAMES=SALIDA1,INCLUDE=(39,10,CH,EQ,C'ASALARIADO'),
                       OUTREC=(10,29)
OUTFIL FNAMES=SALIDA2,INCLUDE=(39,10,CH,EQ,C'AUTONOMO  '),
                       OUTREC=(10,29)

La salida quedará del siguiente modo:

SALIDA1 - ASALARIADOS:


----+----1----+----2----+----
JAVIER    MARTINEZ   CARRETERO


SALIDA2 - AUTONOMOS:


----+----1----+----2----+----
ANTONIO   VILLA     SUSO     
YOLANDA   LOPEZ     ALONSO   
JOSE      LOPEZ     PITA     
CARLOS    POLO      DEL BARRO
CARLOS    PEREZ     FANO     


STARTREC/ENDREC:
Con OUTFIL no están disponibles las opciones SKIPREC/STOPAFT, en su lugar utilizamos STARTREC y ENDREC con el mismo principio.

Retomando el fichero de entrada anterior:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO 
000000006ANTONIO   VILLA     SUSO     AUTONOMO   
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO   
000000001JOSE      LOPEZ     PITA     AUTONOMO   
000000004CARLOS    POLO      DEL BARROAUTONOMO   
000000003CARLOS    PEREZ     FANO     AUTONOMO   

//SYSIN    DD * 
SORT FIELDS=(10,29,CH,A) 
OUTFIL FNAMES=SALIDA1,ENDREC=1 
OUTFIL FNAMES=SALIDA2,STARTREC=2,ENDREC=4 

Primero se ordenan los registros:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000006ANTONIO   VILLA     SUSO     AUTONOMO   
000000003CARLOS    PEREZ     FANO     AUTONOMO   
000000004CARLOS    POLO      DEL BARROAUTONOMO   
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO 
000000001JOSE      LOPEZ     PITA     AUTONOMO   
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO   

Y luego genera los diferentes ficheros de salida:
SALIDA1:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000006ANTONIO   VILLA     SUSO     AUTONOMO   


SALIDA2:
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000003CARLOS    PEREZ     FANO     AUTONOMO   
000000004CARLOS    POLO      DEL BARROAUTONOMO   
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO 
000000001JOSE      LOPEZ     PITA     AUTONOMO   

SORT vol.1: SORT, INCLUDE.

ACTUALIZADO: comparando zonas de un mismo registro con INCLUDE.

La estructura general de un SORT es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *




PGM=SORT --> Indica el programa a utilizar, en este caso el SORT
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:

SORT

SORT FIELDS --> Ordena los registros a partir del fichero de entrada y los guarda ordenados en el fichero de salida:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=(I,L,T,O,I,L,T,O)

I – Inicio. Posición donde empieza el campo por el que se quiere ordenar
L – Longitud máxima del campo por el que se quiere ordenar
T – Tipo de dato del campo que se quiere ordenar:
       CH --> Alfanumérico o numérico normal(sin COMP)
       BI --> Hexadecimal (campos COMP)
       PD --> Empaquetado con o sin signo(campos COMP-3)
O – Orden. A-Ascendente, D- Descendente

Ejemplo:

Ordenar el siguiente fichero por Número y Nombre de cliente en orden ascendente:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO
000000006ANTONIO   VILLA     SUSO     AUTONOMO
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO
000000001JOSE      LOPEZ     PITA     AUTONOMO
000000004CARLOS    POLO      DEL BARROAUTONOMO
000000003CARLOS    PEREZ     FANO     AUTONOMO

Fórmula:

SORT FIELDS=(1,9,CH,A,10,10,CH,A)

Resultado:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000001JOSE      LOPEZ     PITA     AUTONOMO
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO
000000003CARLOS    PEREZ     FANO     AUTONOMO
000000004CARLOS    POLO      DEL BARROAUTONOMO
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO
000000006ANTONIO   VILLA     SUSO     AUTONOMO

Otra opción que tiene el SORT es la siguiente:

SORT FIELDS=COPY

Con ella no indicamos ningún tipo de orden, por lo cual, el fichero de entrada se grabará en salida con el mismo orden.


INCLUDE

Filtra los registros deseados por la condición que se indique:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 INCLUDE COND=(I,L,T,C,V)

I – Inicio. Posición donde empieza el campo por el que se quiere filtrar
L – Longitud máxima del campo por el que se quiere filtrar
T – Tipo de dato del campo que se quiere filtrar:
       CH - Carácter o numérico normal(sin COMP)
       BI - Hexadecimal (campos COMP)
C – Condición de la igualdad que se quiere realizar:
       EQ – Igual
       NE - Distinto
       GE – Mayor o igual
       GT - Mayor
       LE – Menor o igual
       LT - Menor
V – Valor del dato por el que se quiere filtrar
       X’001A‘ – Indica un valor hexadecimal o empaquetado
       C’AL12’ – Indica un valor alfanumérico

Ejemplos:

Ejemplo 1. Vamos a realizar un paso de SORT que realice un filtrado del fichero indicado, para quedarse con los clientes que cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6):

Copy:

01 ENTRADA1.
   05 ENTRADA1-NUMCLI    PIC 9(9).
   05 ENTRADA1-NOMBRE    PIC X(10).
   05 ENTRADA1-APELLID1  PIC X(10).
   05 ENTRADA1-APELLID2  PIC X(10).
   05 ENTRADA1-TIPO      PIC X(11).
   05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
   05 ENTRADA1-TLFNO     PIC 9(9).
   05 FILLER             PIC X(9) VALUE SPACES.

Fichero entrada:

=COLS>
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      983275586
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001FFFFFFFFF444444444
00000000211595900004193955900319953596121319914600000C983275586000000000
------------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        918514535
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003FFFFFFFFF444444444
00000000615365960005933100000242600000143656460000000C918514535000000000
------------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        988453548
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001FFFFFFFFF444444444
00000000586315410003675900000136526000143656460000000C988453548000000000
------------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        676757687
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001FFFFFFFFF444444444
00000000116250000003675900000793100000143656460000000C676757687000000000
------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        666415887
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003FFFFFFFFF444444444
00000000431936200007636000000453021996143656460000000C666415887000000000
------------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        986115484
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001FFFFFFFFF444444444
00000000331936200007595900000615600000143656460000000C986115484000000000
------------------------------------------------------------------------

Fórmula:

INCLUDE COND=(39,8,CH,EQ,C'AUTONOMO',AND,55,1,CH,EQ,C'6')


Fichero salida:

=COLS> ----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000001JOSE      LOPEZ     PITA     AUTONOMO        676757687
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001FFFFFFFFF444444444
00000000116250000003675900000793100000143656460000000C676757687000000000
-------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        666415887
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003FFFFFFFFF444444444
00000000431936200007636000000453021996143656460000000C666415887000000000
-------------------------------------------------------------------------


Ejemplo 2. Vamos a realizar un paso de SORT similar al anterior, que realice un filtrado del fichero indicado, para quedarse con los clientes que cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6). Pero en este caso el número de teléfono vendrá empaquetado(COMP-3):

Copy:

01 ENTRADA1.
   05 ENTRADA1-NUMCLI    PIC 9(9).
   05 ENTRADA1-NOMBRE    PIC X(10).
   05 ENTRADA1-APELLID1  PIC X(10).
   05 ENTRADA1-APELLID2  PIC X(10).
   05 ENTRADA1-TIPO      PIC X(11).
   05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
   05 ENTRADA1-TLFNO     PIC 9(9) COMP-3.
   05 FILLER             PIC X(13) VALUE SPACES.

Fichero entrada:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      q Íì%
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001937564444444444444
00000000211595900004193955900319953596121319914600000C8258C0000000000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        q Î %
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003937164444444444444
00000000615365960005933100000242600000143656460000000C8265C0000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ 
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001937724444444444444
00000000586315410003675900000136526000143656460000000C6858C0000000000000
-----------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        #jéì%
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001695564444444444444
00000000116250000003675900000793100000143656460000000C9118C0000000000000
-----------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        ÅÂÌì%
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003667564444444444444
00000000431936200007636000000453021996143656460000000C7288C0000000000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        m nç%
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001939464444444444444
00000000331936200007595900000615600000143656460000000C4558C0000000000000
-----------------------------------------------------------------------

Fórmula:

 INCLUDE COND=(39,8,CH,EQ,C'AUTONOMO',AND,
    (55,5,BI,GE,X'600000000C',AND,55,5,BI,LT,X'700000000C'))

Resultado:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000001JOSE      LOPEZ     PITA     AUTONOMO        #jéì%
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001695564444444444444
00000000116250000003675900000793100000143656460000000C9118C0000000000000
------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        ÅÂÌì%
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003667564444444444444
00000000431936200007636000000453021996143656460000000C7288C0000000000000
------------------------------------------------------------------------


NOTA: a la hora de comparar con valor (EQ, NE, GT...) podemos utilizar para la comparación otra zona del fichero:

Fichero entrada:
----+----1----+----2-
XXXXX111111XXXXX
YYYYY111111XXXXX
ZZZZZ111111ZZZZZ
WWWWW111111XXXXX

Fórmula:
INCLUDE COND =(1,5,CH,EQ,12,5,CH)

Resultado:
----+----1----+----2-
XXXXX111111XXXXX
ZZZZZ111111ZZZZZ

Hemos comparado las posiciones 1 a 5 con las posiciones 12 a 16 del mismo registro.

lunes, 23 de noviembre de 2020

SORT vol.4: SKIPREC, STOPAFT.

ACTUALIZADO: añadido ejemplo de OPTION SKIPREC para saltarnos registros a la hora de ordenar.

La estructura general de un SORT es la siguiente:

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//         DD DSN=nombre.fichero.entrada2(opcional),DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=CYL,500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *




PGM=SORT --> Indica el programa a utilizar, en este caso el SORT.
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:

OPTION SKIPREC

Sirve para saltar registros a la hora de escribir/ordenar un fichero de salida. Se salta tantos registros del fichero de entrada como se indiquen y a partir de ahí escribe en la salida/ordena.

Ejemplo de copy:
//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 OPTION SKIPREC=número_de_registros_a_saltar

Por ejemplo, tenemos un fichero de entrada con 100 registros, si indicamos "OPTION SKIPREC=20", en el fichero de salida escribirá los registros comprendidos entre 21 y 100 ambos inclusive.

Ejemplo de sort:
//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)') 
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR 
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100)) 
//SYSOUT   DD SYSOUT=* 
//SYSPRINT DD SYSOUT=* 
//SYSIN    DD *
 SORT FIELDS=(1,10,C,A) 
 OPTION SKIPREC=número_de_registros_a_saltar

Por ejemplo, cuando tenemos un fichero que lleva una cabecera en el primer registro (el primer registro tiene un formato distinto al resto del fichero), podemos saltarnos ese primer registro en la ordenación indicando "OPTION SKIPREC=1".
Los registros saltados son eliminados y se ordenarán los registros del 2 en adelante.

NOTA: si queremos guardarnos todos los registros podemos usar OUTFIL con STARTREC y ENDREC.


OPTION STOPAFT

Sirve para dejar de escribir en salida una vez llegado al número de registros indicado.

//SORT001  EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN   DD DSN=nombre.fichero.entrada1,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.salida1,
//            DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT   DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
 SORT FIELDS=COPY
 OPTION STOPAFT=número_de_registro_que_para

Por ejemplo, tenemos un fichero de entrada con 100 registros, si indicamos "OPTION STOPAFT=30", nos escribirá en salida los registros comprendidos entre 1 y 30, ambos inclusive.

OPTION SKIPREC/STOPAFT

Se pueden combinar ambas utilidades del siguiente modo:

OPTION SKIPREC=número_de_registros_a_saltar,
       STOPAFT=número_de_registro_que_para

Por ejemplo, tenemos un fichero de 100 registros, y queremos grabar en salida los comprendidos entre el 30 y 40 ambos inclusive. El método sería el siguiente:

OPTION SKIPREC=29,STOPAFT=11

lunes, 7 de mayo de 2012

JCL Avanzado I. Incluir condiciones IF THEN

Actualizado: Paso para comprobar si un fichero existe y otro modo de incluir condiciones IF/ELSE.

Os dejo otra pequeña utilidad para que un jcl ejecute un paso o no en función de una condición.
Vamos a aplicar las condiciones para hacer que un jcl ejecute un paso u otro en función de si un fichero tiene datos o está vacío

Lo primero que hacemos es verificar que el fichero tiene datos o no:

//**=======================================================*
//** PASO01 - COMPRUEBA SI EL FICHERO TIENE DATOS O ESTÁ VACIO
//**=======================================================*
//PASO01   EXEC PGM=IDCAMS
//IN       DD DSN=nombre.fichero.prueba1,DISP=SHR
//SYSPRINT DD SYSOUT=*
//SYSIN    DD *
  PRINT INFILE(IN) COUNT(1)
  IF MAXCC=12 THEN SET MAXCC=4
/*

Lo segundo es incluir la condición en el paso para que se ejecute en función de éste:


//**=======================================================*
//** PASO02 - REALIZA EL PASO SI SE CUMPLE LA CONDICIÓN    
//**=======================================================*
//PASO02   EXEC SORTD,COND=(4,EQ,PASO01)
//SYSOUT   DD SYSOUT=*
//SORTIN   DD DSN=nombre.fichero.prueba1,DISP=SHR
//SORTOUT  DD DSN=nombre.fichero.prueba2,
//            DISP=(,CATLG),
//            SPACE=(CYL,(100,100),RLSE)
//SYSIN    DD *
  SORT FIELDS=COPY

Posibles resultados:

- Si existe y tiene datos --> El primer paso dice que todo es correcto (MAXXCC=0) y se ejecuta el segundo paso.
- Si existe pero está vacío --> El primer paso da un MAXXCC=4 y no se ejecuta el siguiente paso
- Si no existe --> El jcl abenda dando un FLUSH

Si lo que quieres es lo contrario, es decir, que ejecute el paso solo cuando el fichero esté vacío, pon: COND=(0,EQ,PASO01) en vez de COND=(4,EQ,PASO01).

NOTAS:
- Si se quiere aplicar la condición a más pasos posteriores únicamente añadir el COND=(X,EQ,PASO01) en cada paso.
- Ojo con poner correctamente el nombre del paso en el COND=(0,EQ,PASO01). Puede ser cualquier nombre pero debe coincidir con el que hace la validación de fichero vacío.


Otra manera de incluir condiciones IF/ELSE:
Vamos a construir un paso de JOB que comprueba si un fichero existe.
OJO! No estamos comprobando si lleva datos, sólo si existe.

//**=======================================================*
//** PASO01 - COMPRUEBA SI EL FICHERO EXISTE
//**=======================================================*
//PASO01 EXEC PGM=IDCAMS
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
 LISTCAT ENTRIES (nombre.fichero.prueba1) ALL
 IF LASTCC NE 0 THEN DO
    SET MAXCC=4
    END
/*
//**********************************************************
//**CONDICION PARA EJECUTAR EL SIGUIENTE PASO
//**SOLO SI EL FICHERO EXISTE*
//**********************************************************
//CONDIC1 IF (PASO01.RC > 0) THEN
//* NO EJECUTA BLOQUE CONDIC1 PORQUE EL FICHERO NO EXISTE
//CONDIC1 ELSE
//*******************************************************
//** PASO 02 A EJECUTAR. POR EJEMPLO UN SORT:
//*******************************************************
//PASO02 EXEC SORTD
//SYSOUT  DD SYSOUT=*
//SORTIN  DD DSN=nombre.fichero.prueba1,DISP=SHR
//SORTOUT DD DSN=nombre.fichero.prueba2,
//           DISP=(,CATLG),
//           SPACE=(CYL,(100,100),RLSE)
//SYSIN DD *
SORT FIELDS=COPY
/*
//CONDIC1 ENDIF

En primer lugar utilizamos el programa IDCAMS para comprobar si el fichero existe con la instrucción LISTCAT. Si el fichero no existe, el Return Code (RC) será 4.

Lo siguiente que hacemos es crear un paso CONDIC1 con la sentencia IF, donde preguntamos si el RC del PASO01 es mayor que cero. Si es mayor que cero significa que el fichero no existe, por lo que no haremos nada. En otro caso, ejecutamos los siguientes pasos del JOB.

OJO! Todas las partes de un mismo IF deben ir precedidas del mismo nombre de paso. En nuestro ejemplo CONDIC1.
Todo IF debe terminar con un ENDIF.
La sentencia ELSE no es obligatoria.

lunes, 19 de septiembre de 2011

Sort vol.7: OMIT.

La estructura general de un SORT es la siguiente:

//SORT001 EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN DD DSN=nombre.fichero.entrada1,DISP=SHR
// DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT DD DSN=nombre.fichero.salida1,
// DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *




PGM=SORT --> Indica el programa a utilizar, en este caso el SORT
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:

OMIT

Excluye los registros deseados por la condición que se indique:

//SORT001 EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN DD DSN=nombre.fichero.entrada1,DISP=SHR
// DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT DD DSN=nombre.fichero.salida1,
// DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
SORT FIELDS=COPY
OMIT COND=(I,L,T,C,V)

I – Inicio. Posición donde empieza el campo por el que se quiere filtrar
L – Longitud máxima del campo por el que se quiere filtrar
T – Tipo de dato del campo que se quiere filtrar:
CH - Carácter o numérico normal(sin COMP)
BI - Hexadecimal (campos COMP)
C – Condición de la igualdad que se quiere realizar:
EQ – Igual
NE - Distinto
GE – Mayor o igual
GT - Mayor
LE – Menor o igual
LT - Menor
V – Valor del dato por el que se quiere filtrar
X’001A‘ – Indica un valor hexadecimal o empaquetado
C’AL12’ – Indica un valor alfanumérico

Ejemplos:

Ejemplo 1. Vamos a realizar un paso de SORT que realice un filtrado del fichero indicado, para quedarse con los clientes que NO cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6), es decir, se excluirán del fichero de salida aquellos registros que SI cumplan esa condición:

Copy:

01 ENTRADA1.
05 ENTRADA1-NUMCLI PIC 9(9).
05 ENTRADA1-NOMBRE PIC X(10).
05 ENTRADA1-APELLID1 PIC X(10).
05 ENTRADA1-APELLID2 PIC X(10).
05 ENTRADA1-TIPO PIC X(11).
05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
05 ENTRADA1-TLFNO PIC 9(9).
05 FILLER PIC X(9) VALUE SPACES.


Fichero entrada:

=COLS>
----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      983275586
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001FFFFFFFFF444444444
00000000211595900004193955900319953596121319914600000C983275586000000000
------------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        918514535
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003FFFFFFFFF444444444
00000000615365960005933100000242600000143656460000000C918514535000000000
------------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        988453548
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001FFFFFFFFF444444444
00000000586315410003675900000136526000143656460000000C988453548000000000
------------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        676757687
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001FFFFFFFFF444444444
00000000116250000003675900000793100000143656460000000C676757687000000000
------------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        666415887
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003FFFFFFFFF444444444
00000000431936200007636000000453021996143656460000000C666415887000000000
------------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        986115484
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001FFFFFFFFF444444444
00000000331936200007595900000615600000143656460000000C986115484000000000
------------------------------------------------------------------------


Fórmula:

OMIT COND=(39,8,CH,EQ,C'AUTONOMO',AND,55,1,CH,EQ,C'6')


Fichero salida:

-----------------------------------------------------------------------
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      983275586
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001FFFFFFFFF44444444
00000000211595900004193955900319953596121319914600000C98327558600000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        918514535
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003FFFFFFFFF44444444
00000000615365960005933100000242600000143656460000000C91851453500000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        988453548
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001FFFFFFFFF44444444
00000000586315410003675900000136526000143656460000000C98845354800000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        986115484
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001FFFFFFFFF44444444
00000000331936200007595900000615600000143656460000000C98611548400000000



Ejemplo 2. Vamos a realizar un paso de SORT similar al anterior, que realice un filtrado del fichero indicado, para quedarse con los clientes que NO cumplan lo siguiente: Sean AUTONOMOS y su número de teléfono sea un móvil (comience por 6) , es decir, se excluirán del fichero de salida aquellos registros que SI cumplan esa condición. Pero en este caso el número de teléfono vendrá empaquetado(COMP-3):

Copy:

01 ENTRADA1.
05 ENTRADA1-NUMCLI PIC 9(9).
05 ENTRADA1-NOMBRE PIC X(10).
05 ENTRADA1-APELLID1 PIC X(10).
05 ENTRADA1-APELLID2 PIC X(10).
05 ENTRADA1-TIPO PIC X(11).
05 ENTRADA1-CATEGORIA PIC 9(9) COMP-3.
05 ENTRADA1-TLFNO PIC 9(9) COMP-3.
05 FILLER PIC X(13) VALUE SPACES.


Fichero entrada:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7--
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      q Íì%
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD400001937564444444444444
00000000211595900004193955900319953596121319914600000C8258C0000000000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        q Î %
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD44400003937164444444444444
00000000615365960005933100000242600000143656460000000C8265C0000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD44400001937724444444444444
00000000586315410003675900000136526000143656460000000C6858C0000000000000
-----------------------------------------------------------------------
000000001JOSE      LOPEZ     PITA     AUTONOMO        #jéì%
FFFFFFFFFDDEC444444DDDCE44444DCEC44444CEEDDDDD44400001695564444444444444
00000000116250000003675900000793100000143656460000000C9118C0000000000000
-----------------------------------------------------------------------
000000004CARLOS    POLO      DEL BARROAUTONOMO        ÅÂÌì%
FFFFFFFFFCCDDDE4444DDDD444444CCD4CCDDDCEEDDDDD44400003667564444444444444
00000000431936200007636000000453021996143656460000000C7288C0000000000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        m nç%
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD44400001939464444444444444
00000000331936200007595900000615600000143656460000000C4558C0000000000000
-----------------------------------------------------------------------


Fórmula:

OMIT COND=(39,8,CH,EQ,C'AUTONOMO',AND,
(55,5,BI,GE,X'600000000C',AND,55,5,BI,LT,X'700000000C'))


Resultado:

-----------------------------------------------------------------------
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      q Íì%
FFFFFFFFFDCECCD4444DCDECDCE44CCDDCECDDCECDCDCCCD40000193756444444444444
00000000211595900004193955900319953596121319914600000C8258C000000000000
-----------------------------------------------------------------------
000000006ANTONIO   VILLA     SUSO     AUTONOMO        q Î %
FFFFFFFFFCDEDDCD444ECDDC44444EEED44444CEEDDDDD4440000393716444444444444
00000000615365960005933100000242600000143656460000000C8265C000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD4440000193772444444444444
00000000586315410003675900000136526000143656460000000C6858C000000000000
-----------------------------------------------------------------------
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        o ÍÌ
FFFFFFFFFEDDCDCC444DDDCE44444CDDDED444CEEDDDDD4440000193772444444444444
00000000586315410003675900000136526000143656460000000C6858C000000000000
-----------------------------------------------------------------------
000000003CARLOS    PEREZ     FANO     AUTONOMO        m nç%
FFFFFFFFFCCDDDE4444DCDCE44444CCDD44444CEEDDDDD4440000193946444444444444
00000000331936200007595900000615600000143656460000000C4558C000000000000


Como veis hemos utilizado los mismos ficheros de entrada que para el caso del INCLUDE. El resultado es que ahora obtenemos en el fichero de salida los registros que con el INCLUDE no se mostraban, es decir, justo lo contrario.

lunes, 5 de septiembre de 2011

Sort vol.2.2: OUTREC. Máscaras de edición

FICHERO DE ENTRADA

Supongamos que tenemos este fichero, en el que tenemos los siguientes campos sin formatear:

- una fecha (posiciones del 5 al 10)
- una hora (del 20 al 25)
- importe 1 comprimido (del 26 al 31)
- importe 2 (del 32 al 35)
- importe 3 (del 36 al 45)
- importe 4 (del 46 al final)


----+----1----+----2----+----3----+----4----+----5----+
***************************** Top of Data *************
0001100811MARIA    143010      011100001111110000111111
FFFFFFFFFFDCDCC4444FFFFFF000001FFFFFFFFFFFFFFFFFFFFFFFF
000110081141991000014301000000C011100001111110000111111
-------------------------------------------------------
0002230411VICTOR   153523      022200002222220000222222
FFFFFFFFFFECCEDD444FFFFFF000002FFFFFFFFFFFFFFFFFFFFFFFF
000223041159336900015352300000C022200002222220000222222
-------------------------------------------------------
0003150811MARIANO  164022      033300003333330000333333
FFFFFFFFFFDCDCCDD44FFFFFF000003FFFFFFFFFFFFFFFFFFFFFFFF
000315081141991560016402200000C033300003333330000333333
-------------------------------------------------------
0004251211LUCIA    174515     <044400004444440000444444
FFFFFFFFFFDECCC4444FFFFFF000004FFFFFFFFFFFFFFFFFFFFFFFF
000425121134391000017451500000C044400004444440000444444



Con este ejemplo vamos a aprender a dar el formato que queramos a cada uno de estos campos. Para ello utilizaremos un OUTREC, en donde vamos a tener este fichero de entrada y otro de salida donde saldrán los campos formateados. En este OUTREC vamos a aplicar las MASCARAS. Las máscaras simplemente son herramientas que nos van a permitir modificar el formato de los campos seleccionados con el OUTREC:


//PASO040 EXEC SORTD,OUT=*
//SYSOUT  DD SYSOUT=*
//SORTIN  DD DSN=fichero_de_entrada,DISP=SHR
//SORTOUT DD DSN=fichero_de_salida,
//           DISP=(,CATLG),
//           SPACE=(CYL,(150,75),RLSE)
//SYSIN DD *
SORT FIELDS=COPY
OUTREC FIELDS=(01,04,
               05,06,ZD,M9,LENGTH=8,
               11,09,
               20,06,ZD,M8,LENGTH=8,
               26,06,PD,
               32,04,ZD,M18,LENGTH=4,
               36,10,ZD,M4,LENGTH=11,
               46,10,ZD,M26,LENGTH=11)



En el fichero_de_salida obtendremos como RESULTADO:

----+----1----+----2----+----3----+----4----+----5----+----6----+--
***************************** Top of Data *************************
000110/08/11MARIA    14:30:10     11.11  +1,111.11+0000111111
000223/04/11VICTOR   15:35:23     22.22  +2,222.22+0000222222
000315/08/11MARIANO  16:40:22     33.33  +3,333.33+0000333333
000425/12/11LUCIA    17:45:15     44.44  +4,444.44+0000444444


Por ejemplo, en el primer caso (01,04), simplemente hemos seleccionado el campo pero no hemos aplicado ninguna máscara.
Sin embargo, en el segundo (05,06,ZD,M9,LENGTH=8), hemos seleccionado el campo 'fecha' que ocupa 6 posiciones(DDMMAA) y la hemos aplicado el código de máscara M9 que lo que hace es meter una '/' entre medias formateando el campo a DD/MM/AA.

Para el campo 'hora' hemos hecho lo mismo pero aplicando el código M8, que convierte un formato HHMMSS en HH:MM:SS.
Para los importes también hemos aplicado otros códigos, por ejemplo el M4 que pone a una cantidad un signo(+ o -), una coma para separar los miles y un punto para separar los decimales.

Existe una tabla donde están reflajados los códigos de conversión de las máscaras. Os dejo la que tengo para descargar, si encontráis más códigos de conversión por favor indicarlos.

Lista de códigos de conversión de las máscaras

Tengo entendido que puedes formar tus propias máscaras a partir de estos valores, y así no utilizar los códigos de conversión. De ese modo es más libre y cada uno puede formatear según le interese. Cuando sepa como se hace lo indico, estoy en ello...


MÁS UTILIDADES DE LAS MÁSCARAS.

El ejemplo anterior nos permite dar un formato más leíble a nuestros ficheros, pero además si tu host lo permite, podemos exportar este fichero fuera del host, y visualizarlo en una hoja de cálculo. Para ello, podemos preparar el fichero para abrirlo por ejemplo con el Excel. Solo tenemos que poner un ';' entre cada campo del siguiente modo:

//PASO040 EXEC SORTD,OUT=*
//SYSOUT DD SYSOUT=*
//SORTIN DD DSN=LAET.LAEHISTA.CCOBOL,DISP=SHR
//SORTOUT DD DSN=LAET.MASCARA.SALIDA,
// DISP=(,CATLG),
// SPACE=(CYL,(150,75),RLSE)
//SYSIN DD * 

SORT FIELDS=COPY
OUTREC FIELDS=(01,04,C';',
               05,06,ZD,M9,LENGTH=8,C';',
               11,09,C';',
               20,06,ZD,M8,LENGTH=8,C';',
               26,06,PD,C';',
               32,04,ZD,M18,LENGTH=4,C';',
               36,10,ZD,M4,LENGTH=11,C';',
               46,10,ZD,M26,LENGTH=11)



RESULTADO:

----+----1----+----2----+----3----+----4----+----5----+----6----+----7----
***************************** Top of Data ********************************
0001;10/08/11;MARIA    ;14:30:10;    1;1.11;  +1,111.11;+0000111111
0002;23/04/11;VICTOR   ;15:35:23;    2;2.22;  +2,222.22;+0000222222
0003;15/08/11;MARIANO  ;16:40:22;    3;3.33;  +3,333.33;+0000333333
0004;25/12/11;LUCIA    ;17:45:15;    4;4.44;  +4,444.44;+0000444444


Ahora solo hay que exportar el fichero host a un archivo excel poniendo al archivo la extensión .CSV (por ejemplo: "ejemplo_mascaras.csv").
De este modo el excel utiliza los ';' para separar los campos en celdas y que cada campo quede organizado en su correspondiente columna. Si has seguido el ejemplo te ha de quedar de este modo:


lunes, 20 de junio de 2011

SORT vol.6: INREC.

La estructura general de un SORT es la siguiente:

//SORT001 EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN DD DSN=nombre.fichero.entrada1,DISP=SHR
//       DD DSN=nombre.fichero.entrada2(opcional),DISP=SHR
//SORTOUT DD DSN=nombre.fichero.salida1,
//           DISP=(,CATLG,DELETE),SPACE=(CYL,(500,100))
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *



PGM=SORT --> Indica el programa a utilizar, en este caso el SORT.
PARM=('DYNALLOC=(SYSALLDA,32)') --> Cantidad de memoria que se da a la ejecución del paso. Si se queda corto, aumentarla en valores de 8,12,32,64,128, 256 (como las memorias RAM)
SORTIN --> Ficheros de entrada
SORTOUT --> Ficheros de salida
SYSIN --> Indica el tipo de sort a realizar, las opciones disponibles son muchas y muy variadas, pudiendo utilizarse varias juntas en un mismo paso. Algunas de ellas son SORT, SUM, OMIT, INCLUDE, INREC, OUTREC, OUTFIL, OPTION … .

En este documento se explica en detalle algunas de estas funciones:

INREC

INREC FIELDS --> Toma los registros del fichero de entrada y los guarda formateados en el fichero de salida. A diferencia del OUTREC, el INREC modifica los registros de entrada antes de ordenarlos.

//SORT001 EXEC PGM=SORT,PARM=('DYNALLOC=(SYSALLDA,32)')
//SORTIN DD DSN=nombre.fichero.entrada1,DISP=SHR
//       DD DSN=nombre.fichero.entrada2,DISP=SHR
//SORTOUT DD DSN=nombre.fichero.salida1,
//           DISP=(,CATLG,DELETE),SPACE=CYL,500,100))
//SYSOUT DD SYSOUT=*
//SYSPRINT DD SYSOUT=*
//SYSIN DD *
  SORT FIELDS=...
  INREC FIELDS=(I,L,D(opcional))

I – Inicio. Posición donde empieza el campo.
L – Longitud máxima del campo.
D – Dato a incluir (opcional).

Hay diferentes formas y ejemplos de utilizar el INREC, no voy a explicarlas pues se realizan del mismo modo que en el OUTREC (Ir al artículo):

- FORMATEO DE FICHEROS - Seleccionar y alterar los campos de los registros del fichero de entrada.
– CONVERSIÓN DE DATOS - Permite cambiar el formato de los campos. Se realiza del siguiente modo:
- CHANGE – Cambiar datos - Sustituir datos del fichero por otros.
- CONDICIONES - IFTHEN. Incluir condiciones

NOTA:La forma de codificar es la misma que en el OUTREC pero poniendo INREC. Lo único que se ha de tener en cuenta es acordarse que va a realizar la operación antes de ordenar el/los fichero/s de entrada. En algunas operaciones hay que tener en cuenta esta situación porque el resultado puede variar.

miércoles, 8 de junio de 2011

JCL Básico IV: Sentencia DD (Parte III)

Continuamos con el último apartado de la sentencia DD. Vamos a hablar de todos los posibles parámetros que se pueden indicar en una sentencia DD DSN.

DSN ó DSNAME
Sirve para indicar el nombre del fichero en donde vamos ha guardar la salida. Por ejemplo, un programa con dos ficheros de entrada y dos de salida quedaría del siguiente modo:

//PAS01 EXEC PGM=MIPROGRAMA
//ENTRADA1 DD DSN=xxxx.nombre.fichero1,DISP=SHR
//ENTRADA2 DD DSN=xxxx.nombre.fichero2,DISP=SHR
//SALIDA1 DD DSN=xxxx.nombre.fichero3,
// ...
//SALIDA2 DD DSN=xxxx.nombre.fichero4,
// ...

¿Qué nombre he de dar al fichero?

El nombre que des a un fichero es libre pero teniendo en cuenta las reglas obligatorias que marca el host y las reglas opcionales que te marque la arquitectura donde te encuentres.
Como las reglas de arquitectura van en función del entorno donde te encuentres voy a comentar las reglas del host:
- Nombres simples: Un único nombre de 8 posiciones alfanuméricas en donde el primer carácter alfabético ha de ser uno de los siguientes: @ $ #
- Nombres compuestos: Puede tener varios nombres simples separados por puntos siempre y cuando el total de posiciones(incluidos los puntos) no supere las 44 posiciones.
- Nombres de ficheros particionados: los explicaré más adelante
- Nombres de ficheros temporales: los explicaré más adelante
- Nombres de ficheros generacionales: los explicaré más adelante
- Nombres que referencian a ficheros anteriores:

Una opción es utilizar "DSN=NULLFILE" en vez de "DD DUMMY"

Estos dos ejemplo son lo mismo:

//PAS01 EXEC PGM=MIPROGRAMA
//ENTRADA1 DD DSN=xxxx.nombre.fichero1,DISP=SHR
//ENTRADA2 DD DSN=xxxx.nombre.fichero2,DISP=SHR
//SALIDA1 DD DSN=xxxx.nombre.fichero3,
// ...
//SALIDA2 DD DSN=NULLFILE

//PAS01 EXEC PGM=MIPROGRAMA
//ENTRADA1 DD DSN=xxxx.nombre.fichero1,DISP=SHR
//ENTRADA2 DD DSN=xxxx.nombre.fichero2,DISP=SHR
//SALIDA1 DD DSN=xxxx.nombre.fichero3,
// ...
//SALIDA2 DD DUMMY

DISP
Se usa para indicar la disposición del fichero. Tiene hasta 3 posibles subparámetros:

- El primero indica la disposición del fichero en el estado inicial. Este estado puede ser: NEW, OLD, SHR ó MOD.
- El segundo indica la disposición del fichero en caso de que la ejecución sea correcta. Este estado puede ser: DELETE,KEEP,PASS,CATLG,UNCATLG
- El tercero indica la disposición del fichero en caso de que la ejecución falle. Este estado puede ser DELETE,KEEP,CATLG,UNCATLG

Explico cada uno de ellos:

NEW - El fichero es de nueva creación.
OLD - El fichero existe y se abrirá para uso exlusivo del proceso que lo lance.
SHR - El fichero existe y será compartido con cualquier otro proceso que quiera usarlo.
MOD - Si el fichero existe se abrirá para uso exlusivo del proceso que lo lance. Se posicionará en el ultimo registro y comenzará a escribir a partir de ese último registro. Si el fichero no existe asume DISP=(NEW)

NOTA: Si no se codifica el primer subparámetro (,xxx,xxx) por defecto el sistema pone NEW

DELETE - Se elimina el fichero tras la ejecución.
Si (,DELETE,xxx) --> en caso de que el paso termine bien se borra el fichero
Si (,xxx,DELETE) --> en caso de error se borra el fichero
Si (,DELETE,DELETE) --> tanto si el paso termina bien como si no, en cualquier caso se borra el fichero

KEEP - El fichero se guarda al final del paso. El sistema no guarda la dirección del fichero y por ello deberemos referenciar todos los datos para recuperar la información del mismo
Si (,KEEP,xxx) --> en caso de que el paso termine bien se guarda
Si (,xxx,KEEP) --> en caso de error se guarda el fichero
Si (,KEEP,KEEP) --> tanto si el paso termina bien como si no, en cualquier caso se guarda el fichero

PASS - Permite utilizar el fichero solo durante la ejecución del jcl. Una vez terminada la ejecución el fichero se borra solo.

CATLG - Permite guardar el fichero una vez creado. Puedes utiliar el fichero una vez terminada la ejecución. Siguiendo con el ejemplo:
Si (,CATLG,xxx) --> en caso de que el paso termine bien se cataloga
Si (,xxx,CATLG) --> en caso de error se cataloga el fichero
Si (,CATLG,CATLG) --> tanto si el paso termina bien como si no, en cualquier caso se cataloga el fichero

UNCATLG - Se borra la dirección del catalogo del acceso a un fichero

NOTA: Los valores por defecto son:
Si no pones nada o pones DISP=(NEW) por defecto el sistema toma --> DISP=(NEW,DELETE,DELETE)
Si pones solo DISP=(OLD) el sistema toma por defecto DISP=(OLD,KEEP,KEEP)
Si pones solo DISP=(SHR) el sistema toma por defecto DISP=(SHR,KEEP,KEEP)

Como ejemplos de estas combinaciones pueden salir muchos, os lo dejo en vuestras manos. Simplemente es ir combinando los 3 subparámetros para obtener el resultado esperado.

UNIT
Sirve para especificar en que tipo de dispositivo queremos guardar el fichero:
UNIT=dispositivo

SYSALLDA - Dispositivo de acceso directo (Disco). Uso: UNIT=SYSALLDA
TAPE - Cinta. Uso: UNIT=TAPE
TA80 - Cartucho. Uso: UNIT=TA80
TA90 - Cartucho de alta densidad . Uso: UNIT=TA90

SPACE
Se utiliza para asignar el espacio necesario para catalogar un fichero. Consta de varios subparámetros:

SPACE=(unidad,(mem_primaria,mem_secundaria,num_bloq),RLSE,tipo_asig,ROUND)
Un ejemplo: SPACE=(CYL,(250,125),RLSE,,)

Unidad --> Lo primero en hacer es elegir la unidad de medida del espacio, teniendo en cuenta que:
- TRK: El espacio necesario se pide en pistas. PISTAS = (LONG.REGISTRO * NUM.REGISTROS) / 47474
- CYL: El espacio necesario se pide en cilindros.
Generalmente este se utiliza para cadenas de JCL que utiliza 15 pistas.
Ojo este prácticamente no libera pistas. CILINDROS = PISTAS / 15

Memoria primaria --> Cantidad de memoria que se estima que necesitará el fichero
Memoria secundaria --> cantidad a añadir en caso de sobrepasar la memoria primaria
Número de bloques --> Número de bloques del directorio. Este dato se obtiene mediante:
- FICHEROS PEQUEÑOS Y MEDIANOS.
BLOQUE = (15476 / LONG.REGISTRO) ENTERO * LONG.REGISTRO

- FICHEROS GRANDES.
BLOQUE = (23476 / LONG.REGISTRO) ENTERO * LONG.REGISTRO

RLSE --> Se encarga de liberar el espacio no ocupado tras crear el fichero
Tipo de Asignación:
-CONTIG. Pide que el espacio asignado para la petición primaria sea contiguo
-MXIG. Solicita la asignación del área mayor de espacio libre
-ALX. Solicita la asignación del área mayor de espacio libre no inferior a 5 áreas contiguas
ROUND --> Tiene sentido en espacio por bloques y efectúa el redondeo a número entero de cilindros.

DCB
Con el DCB se definen parámetros del fichero tales como la longitud fija o variable, el tipo de organización o el tipo de particionamiento. Su estructura es:

DCB=(RECFM=?,LRECL=?,BLKSIZE=?,DSORG=?,DEN=?)
Ejemplo: DCB=(RECFM=FB,LRECL=80,BLKSIZE=8000,DSORG=PS)

RECFM:
U-Indefinido
V-Longitud variable
VB-longitud variable bloqueado
F-Longitud fija
FB-Longitud fija bloqueada
FBA-Longitud fija bloqueda con caracteres ASA (para impresión)

LRECL --> Longitud del registro

BLKSIZE --> Longitud del bloqueo. Poner un número múltiplo del LRECL

DSORG --> Tipo de organización
PS-Secuancial
IS-Secuancial Indexado
DA-Organización directa
PO-Particionado

lunes, 23 de mayo de 2011

Sort vol.2.1: OUTREC. IFTHEN

Ampliando un poco las funciones del OUTREC os voy a explicar como incluir condiciones. Es muy sencillo y puede evitar tener que crear programas en un momento dado.

Pongamos el caso de que tenemos el siguiente fichero con los datos de unos clientes:

----+----1----+----2----+----3----+----4----+----5----+----
***************************** Top of Data *****************
000000001JOSE      LOPEZ     PITA     AUTONOMO        47001
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      47001
000000003CARLOS    PEREZ     FANO     AUTONOMO        47001
000000004CARLOS    POLO      DEL BARROAUTONOMO        47001
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        47001
000000006ANTONIO   VILLA     SUSO     AUTONOMO        47001
000000007FULANITO  VILLA     SUSO     AUTONOMO        47001


Un buen día nos dicen que quieren añadir al final de cada registro un indicador que nos marque lo siquiente:

Si es un AUTONOMO añadir el indicador 'A'
Si es un ASALARIADO añadir el indicador 'S'

Utlizaremos el siguiente paso de jcl donde aplicamos la condición:

//OUTREC   EXEC SORTD
//SYSOUT   DD SYSOUT=*
//SORTIN   DD DSN=Nombre_Fichero_De_Entrada,DISP=SHR
//SORTOUT  DD DSN=Nombre_Fichero_De_Salida,
//            DISP=(,CATLG),
//            SPACE=(CYL,(100,100),RLSE)
//SYSIN    DD *
 SORT FIELDS=COPY
 OUTREC IFTHEN=(WHEN=(39,11,CH,EQ,C'AUTONOMO   '),
          OVERLAY=(1,59,C'A')),
        IFTHEN=(WHEN=NONE,
          OVERLAY=(1,59,C'S'))


El resultado obtenido será el siguiente:

----+----1----+----2----+----3----+----4----+----5----+----6
***************************** Top of Data ******************
000000001JOSE      LOPEZ     PITA     AUTONOMO        47001A
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      47001S
000000003CARLOS    PEREZ     FANO     AUTONOMO        47001A
000000004CARLOS    POLO      DEL BARROAUTONOMO        47001A
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        47001A
000000006ANTONIO   VILLA     SUSO     AUTONOMO        47001A
000000007FULANITO  VILLA     SUSO     AUTONOMO        47001A


Vemos como a los AUTONOMOS les marca con una A y a los ASALARIADOS con una S.

Notas:
- Para añadir más condiciones se deben añadir más IFTHEN al OUTREC.
- Esto es válido también para el INREC.

lunes, 16 de mayo de 2011

Sort vol.5.1: SUM. Averiguar registros duplicados

Hola. Os dejo un jcl que os puede sacar de un apuro en más de una ocasión (a mí me salvó más de una vez).
Se trata de un procesito fácil, barato y para toda la familia, que nos permite averiguar que registros de un fichero están duplicados, cuales no y cuantos son.

Como siempre, para que quede más claro seguiré un ejemplo práctico, válido para cualquier caso:

Supongamos que tenemos el siguiente fichero con los duplicados:


----+----1----+----2----+----3----+----4----+----5----
***************************** Top of Data ************
000000001JOSE      LOPEZ     PITA     AUTONOMO        
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      
000000003CARLOS    PEREZ     FANO     AUTONOMO        
000000004CARLOS    POLO      DEL BARROAUTONOMO        
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        
000000006ANTONIO   VILLA     SUSO     AUTONOMO        
000000007FULANITO  VILLA     SUSO     AUTONOMO 
...


Vemos que Javier y Yolanda salen repetidos, Yolanda icluso viene 3 veces. A simple vista los vemos porque el ejemplo está preparado para ello, pero imaginate que el fichero tuviera 100.000 registros y solo 2 duplicados, se complica la búsqueda no? continuamos:

PASO1 - Lo primero que haremos será ordenar el fichero por la clave (en este caso son las primeras 9 posiciones) y después poner un 1 al final de cada uno de los registros del fichero, para ello:


//PASO001  EXEC SORTD
//SYSOUT   DD SYSOUT=*
//SORTIN   DD DSN=nombre_fichero_con_diplicados1,DISP=SHR
//SORTOUT  DD DSN=nombre_fichero_salida1_paso001,
//            DISP=(,CATLG),
//            SPACE=(CYL,(100,100),RLSE)
//SYSIN    DD *
 SORT FIELDS=(1,9,ZD,A)
 OUTREC FIELDS=(1,54,C'1')


El fichero quedará del siguiente modo:


----+----1----+----2----+----3----+----4----+----5----+
***************************** Top of Data *************
000000001JOSE      LOPEZ     PITA     AUTONOMO        1
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      1
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      1
000000003CARLOS    PEREZ     FANO     AUTONOMO        1
000000004CARLOS    POLO      DEL BARROAUTONOMO        1
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        1
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        1
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        1
000000006ANTONIO   VILLA     SUSO     AUTONOMO        1
000000007FULANITO  VILLA     SUSO     AUTONOMO        1
...


PASO2 - Ahora lo que haremos será agrupar los registros por clave y utilizar el numeríto (1) que hemos introducido para sumar los registros que agrupemos:


//PASO002  EXEC SORTD
//SYSOUT   DD SYSOUT=*
//SORTIN   DD DSN=nombre_fichero_salida1_paso001,DISP=SHR
//SORTOUT  DD DSN=nombre_fichero_salida,
//            DISP=(,CATLG),
//            SPACE=(CYL,(100,100),RLSE)
//SYSIN    DD *
 SORT FIELDS=(1,9,ZD,A)
 SUM FIELDS=(55,1,ZD)


Obtendremos el resultado siguiente:


----+----1----+----2----+----3----+----4----+----5----+
***************************** Top of Data *************
000000001JOSE      LOPEZ     PITA     AUTONOMO        1
000000002JAVIER    MARTINEZ  CARRETEROASALARIADO      2
000000003CARLOS    PEREZ     FANO     AUTONOMO        1
000000004CARLOS    POLO      DEL BARROAUTONOMO        1
000000005YOLANDA   LOPEZ     ALONSO   AUTONOMO        3
000000006ANTONIO   VILLA     SUSO     AUTONOMO        1
000000007FULANITO  VILLA     SUSO     AUTONOMO        1
...


Bien, ahora simplemente hacemos busquedas en el fichero teniendo en cuenta lo siguiente:
- Si el numerito introducido al final de cada registro no ha variado (si vale 1), quiere decir que el registro no está duplicado
- Si ha variado el valor querra decir que el registro estaba duplicado y nos dirá el número de veces que está duplicado.

Según el ejemplo vemos como Javier tiene un 2 porque está repetido dos veces, Yolanda tiene un 3 porque está repetida 3 veces, y el resto tienen un 1 porque no están repetidos.

Así de facil!

Otros casos útiles:

En algunas ocasiones queremos camparar dos ficheros para encontrar las direfencias, por ejemplo, suponte que deberían de ser iguales pero uno de ellos tiene 3 registros más que el otro, y que esto pueda ser debido algún registro duplicado.
Para resolverlo, podéis aplicar este mismo método, aplicando el PASO1 a los dos ficheros y luego metiendo los dos ficheros en el PASO2. Te dirá que registros son únicos(tanto de un fichero como del otro), cuales no lo són y el número de los que estén repetidos.

Espero que os haya servido, no obstante cualquier duda comentarla.