Cruzar ficheros mediante SPLICE de ICETOOL
En muchas ocasiones nos podemos encontrar con la necesidad de comparar los registros de dos ficheros distintos con el objetivo de determinar si son iguales en función de una clave determinada o no. Esto, que en principio parece una operativa compleja, puede ser realizado de forma bastante ágil mediante el operador SPLICE de la utilidad ICETOOL.
Tal y como se especifica en la documentación de la herramienta, la función SPLICE sirve para realizar un cruce de ficheros, comparar los registros contenidos en ellos, extraer la información seleccionada y enviarla a un fichero de salida.

Una vez comentado de forma teórica, lo mejor es que veamos cómo funciona el proceso de cruce de ficheros mediante un ejemplo. Para ello, vamos a partir de dos ficheros de diferente longitud de registro. En ambos datasets se va a encontrar la misma clave Población, así que vamos a ejecutar la comparación mediante este campo.
Comparar registros de ficheros mediante SPLICE
En nuestro ejemplo, vamos a usar como entrada un fichero de claves (KEYS) y un fichero maestro (MASTER). En el KEYS tendremos la relación entre los códigos de Población actuales (antiguos) y los códigos de Población nuevos. En el MASTER tendremos los registros de Población con toda su información asociada (uno de esos campos será la clave Población, que figurará inicialmente con el código actual).
En este caso, nos piden que sustituyamos en el MASTER los códigos actuales de las Poblaciones por los códigos nuevos (recordemos que la relación entre ambos figura en el fichero KEYS). Aquí es donde va a entrar en escena el empleo del SPLICE de la utilidad ICETOOL.
El contenido del fichero de relaciones entre claves, denominado SIST.UNLOAD.X0005X.POBL.KEYS, es el siguiente (en primer lugar figura la clave actual y, a continuación, la clave nueva sustituta):
----+----1---
*************
000010-100010
000002-100002
000004-100004
000005-100005
000006-100006
000007-100007
000008-100008
*************

Por otra parte, los registros que tenemos cargados en el fichero de Poblaciones, denominado SIST.UNLOAD.X0005X.POBL.MASTER, son los siguientes:
----+----1----+----2----+----3----+----4
***************************** Top of Data *****
A-000020-MADRID.................MAD00100
B-000019-CIUDAD REAL............CRE00200
A-000018-BARCELONA..............BAR00300
A-000017-VALENCIA...............VAL00400
A-000015-ZARAGOZA...............ZAR00600
B-000014-CASTELLON..............CAS00700
B-000012-GRANADA................GRA00900
B-000011-TOLEDO.................TOL01000
B-000010-SEGOVIA................SEG01100
B-000002-ALMERIA................ALM01300
B-000004-SANTANDER..............SAN01500
B-000005-TARRAGONA..............TAR01600
B-000006-BADAJOZ................BAD01700
B-000007-SALAMANCA..............SAL01800
B-000008-BURGOS.................BUR01900
**************************** Bottom of Data ***
La idea es que, tras lanzar nuestro proceso de conversión, la población Madrid del MASTER, por ejemplo, ya no esté asociada al código antiguo 000020 sino al código nuevo 100020. El resto de campos de los registros del fichero maestro tienen que quedar exactamente igual que ahora.
A continuación, mostramos el código necesario para realizar el cambio comentado.
//* *******************************************
//* * PASO ICETOOL PARA REFORMATEAR ENTRADAS //* * //* *******************************************
//JJ0105 EXEC PGM=ICETOOL //TOOLMSG DD SYSOUT=*
//DFSMSG DD SYSOUT=*
//* KEYS : FICHERO DE RELACIONES ENTRE CLAVES
//KEYS DD DSN= SIST.UNLOAD.X0005X.POBL.KEYS,
// DISP=SHR
//* MASTER: FICHEROS DE POBLACIONES
//MASTER DD DSN= SIST.UNLOAD.X0005X.POBL.MASTER,
// DISP=SHR //* TEMP1 : FICHERO KEYS FORMATEADO Y ORDENADO PARA CRUCE
//TEMP1 DD DSN=SIST.JJ0105T1.X0060X.DDD.POBL.T1,
// DISP=(NEW,CATLG,DELETE), // SPACE=(CYL,(00100,00100),RLSE),
// UNIT=DISCO
//* TEMP2 : F. POBLACIONES FORMATEADO Y ORDENADO PARA CRUCE
//TEMP2 DD DSN=SIST.JJ0105T2. X0060X.DDD.POBL.T2,
// DISP=(NEW,CATLG,DELETE), // SPACE=(CYL,(00100,00100),RLSE),
// UNIT=DISCO
//TOOLIN DD DSN=SIST.SYSIN(JJRS1A03),
// DISP=SHR
//CTL1CNTL DD DSN=SIST.SYSIN(JJRS1A04),
// DISP=SHR
//CTL2CNTL DD DSN=SIST.SYSIN(JJRS1A05),
// DISP=SHR
//JJ0105A EXEC PGM=ABEN3333,
// COND=(4,GE,JJ0105)
//CTRNORST DD DUMMY
//*
//* *******************************************
//* * PASO ICETOOL PARA GENERAR SALIDAS
//* *
//* *******************************************
//JJ0107 EXEC PGM=ICETOOL
//TOOLMSG DD SYSOUT=*
//DFSMSG DD SYSOUT=*
//* CONCAT: FICHERO UNIFICADO PARA REALIZAR EL ICETOOL
//CONCAT DD DSN=SIST.JJ0105T1.X0060X.DDD.POBL.T1,
// DISP=SHR // DD DSN=SIST.JJ0105T2.X0060X.DDD.POBL.T2,
// DISP=SHR
//* OUT : FICHERO DE SALIDA CON LOS REGISTROS MODIFICADOS
//OUT DD DSN=SIST.JJ0107S1.X0060X.DDD.POBL.MD,
// DISP=(NEW,CATLG,DELETE), // SPACE=(CYL,(00100,00100),RLSE),
// UNIT=DISCO
//* OUT1 : F. DE SALIDA CON LOS REGISTROS NO MODIFICADOS
//OUT1 DD DSN=SIST.JJ0107S2.X0060X.DDD.POBL.RS,
// DISP=(NEW,CATLG,DELETE), // SPACE=(CYL,(00100,00100),RLSE),
// UNIT=DISCO
//TOOLIN DD DSN=SIST.SYSIN(JJRS1A06),
// DISP=SHR
//CTL3CNTL DD DSN=SIST.SYSIN(JJRS1A07),
// DISP=SHR
//CTL4CNTL DD DSN=SIST.SYSIN(JJRS1A08),
// DISP=SHR
//JJ0107A EXEC PGM=ABEN3333,
// COND=(4,GE,JJ0107)
//CTRNORST DD DUMMY
//*
Y las fichas asociadas al código anterior son las siguientes:
*--------------------------------------------------------*
* <<< FICHA JJRS1A03 >>>
* COPIA KEYS A FICHERO TEMP1 PARA PERMITIR SPLICE
* COPIA MASTER A TEMP Y AÑADE LOS REGISTROS A COMBINAR
*--------------------------------------------------------*
COPY FROM(KEYS) TO(TEMP1) USING(CTL1)
COPY FROM(MASTER) TO(TEMP2) USING(CTL2)
*--------------------------------------------------------*
* <<< FICHA JJRS1A04 >>>
* REFORMATEAMOS EL KEYS - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
SORT FIELDS=(1,6,CH,A)
OUTREC FIELDS=(1,13,33X,47:C'D',8,6)
*--------------------------------------------------------*
* <<< FICHA JJRS1A05 >>>
* REFORMATEAMOS EL MASTER - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
INREC FIELDS=(3,6,1,40)
SORT FIELDS=(1,6,CH,A)
OUTREC FIELDS=(1,46,47:C' ',6X)
*--------------------------------------------------------*
* <<< FICHA JJRS1A06 >>>
* OUT: REGISTROS QUE COINCIDEN *
* INCLUIMOS TODO DEL MASTER MAS POBLACION NUEVA DE KEY *
* MAS UN INDICADOR NUEVO DE MODIFICADO
* OUT1: RESTO DE REGISTROS QUE NO COINCIDEN *
*--------------------------------------------------------*
SPLICE FROM(CONCAT) TO(OUT) ON(1,6,CH) WITHALL -
WITH(7,40) USING(CTL3)
SPLICE FROM(CONCAT) TO(OUT1) ON(1,6,CH) WITHALL -
WITH(7,40) USING(CTL4) KEEPNODUPS KEEPBASE
*--------------------------------------------------------*
* <<< FICHA JJRS1A07 >>>
* SUSTITUIMOS POBL ENCONTRADOS POR POBL NUEVAS
* SE INCLUYE INDICADOR DE MODIFICADO
*--------------------------------------------------------*
OUTFIL FNAMES=OUT,
INCLUDE=(47,1,CH,EQ,C'D'),
OUTREC=(7,2,48,6,15,32)
*--------------------------------------------------------*
* <<< FICHA JJRS1A08 >>>
* SACAMOS REGISTROS NO ENCONTRADOS PARA CUADRAR ENTRADA
*--------------------------------------------------------*
OUTFIL FNAMES=OUT1,
INCLUDE=(47,1,CH,EQ,C' '),
OUTREC=(7,40)
Como vemos, el código anterior se compone de dos pasos JCL, que son los que vamos a necesitar para, en primer lugar, reformatear e igualar la longitud de los dos ficheros de entrada y, posteriormente, generar un fichero de salida con los registros modificados y otro con los registros no modificados.

Detalle de las fichas requeridas para realizar un SPLICE
A continuación, una vez mostrado el código anterior, vamos a ir revisando con un poco de detalle en qué consisten cada una de las fichas que hemos tenido que crear en los dos pasos del JCL. Como veremos, muchas de ellas son bastante genéricas.
PASO 1: PASO ICETOOL PARA REFORMATEAR ENTRADAS
1º) Invocación a ICETOOL: El primer paso es, como siempre, la invocación a la herramienta ICETOOL mediante el comando EXEC PGM.
//JJ0105 EXEC PGM=ICETOOL
2º) Especificación de los ficheros de entrada: A continuación, indicamos los nombres de los dos ficheros de entrada que vamos a emplear en el ICETOOL. Se trata del fichero de relaciones entre claves (SIST.UNLOAD.X0005X.POBL.KEYS) a emplear y del fichero maestro con los datos de poblaciones (SIST.UNLOAD.X0005X.POBL.MASTER).
//* KEYS : FICHERO DE RELACIONES ENTRE CLAVES
//KEYS DD DSN= SIST.UNLOAD.X0005X.POBL.KEYS,
// DISP=SHR
//* MASTER: FICHEROS DE POBLACIONES
//MASTER DD DSN= SIST.UNLOAD.X0005X.POBL.MASTER,
// DISP=SHR
3º) Especificación de los ficheros de salida: Del mismo modo, también indicamos los nombres de los ficheros que van a contener la información reformateada de KEYS y MASTER. Estos datsets intermedios se denominarán SIST.JJ0105T1.X0060X.DDD.POBL.T1 y SIST.JJ0105T2.X0060X.DDD.POBL.T2.
//* TEMP1 : FICHERO KEYS FORMATEADO Y ORDENADO PARA CRUCE
//TEMP1 DD DSN=SIST.JJ0105T1.X0060X.DDD.POBL.T1,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(00100,00100),RLSE),
// UNIT=DISCO
//* TEMP2 : F. POBLACIONES FORMATEADO Y ORDENADO PARA CRUCE
//TEMP2 DD DSN=SIST.JJ0105T2. X0060X.DDD.POBL.T2,
// DISP=(NEW,CATLG,DELETE),
// SPACE=(CYL,(00100,00100),RLSE),
// UNIT=DISCO
4º) Ficha TOOLIN: Aquí es donde vamos a indicarle a ICETOOL que tiene que proceder a ejecutar el operador COPY en dos ocasiones. La primera de ellas para pasar de KEYS a TEMP1 y la segunda para pasar de MASTER a TEMP2.
*--------------------------------------------------------*
* <<< FICHA JJRS1A03 >>>
* COPIA KEYS A FICHERO TEMP1 PARA PERMITIR SPLICE
* COPIA MASTER A TEMP2 Y AÑADE LOS REGISTROS A COMBINAR
*--------------------------------------------------------*
COPY FROM(KEYS) TO(TEMP1) USING(CTL1)
COPY FROM(MASTER) TO(TEMP2) USING(CTL2)
*--------------------------------------------------------*
* <<< FICHA JJRS1A04 >>>
* REFORMATEAMOS EL KEYS - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
SORT FIELDS=(1,6,CH,A)
OUTREC FIELDS=(1,13,33X,47:C'D',8,6)

La primera ficha de control (CTL1CNTL) hace referencia al COPY de KEYS a TEMP1. Como podemos ver en la codificación de la ficha anterior, en ella se realizan dos cosas con los datos de entrada.
-
Lo primero que hace es ordenar el fichero KEYS en
función del campo de longitud 6 situado en la posición 1 (se trata del campo
código de Población).
-
A continuación, transfiere del KEYS al TEMP1 la
siguiente información de los registros: el campo de longitud 13 que empieza en
la posición 1 (1,13), 33 espacios en blanco (33X), un carácter ‘D’ en la
posición 47 (47:C’D’) y el campo de longitud 6 que empieza en la posición 8
(8,6).
* <<< FICHA JJRS1A05 >>>
* REFORMATEAMOS EL MASTER - LA CLAVE ES LA POBLACION
*--------------------------------------------------------*
INREC FIELDS=(3,6,1,40)
SORT FIELDS=(1,6,CH,A)
OUTREC FIELDS=(1,46,47:C' ',6X)

La segunda ficha de control (CTL2CNTL) hace referencia al COPY de MASTER a TEMP2. Del mismo modo que en la anterior, en esta segunda ficha vemos que también se realizan varias acciones con los datos de entrada.
-
INREC: En primer lugar, a los registros de entrada le
insertamos por delante el campo de longitud 6 que está en la posición 3 (3,6),
que es la Población. A continuación, se incluyen las 40 posiciones de los
registros sin realizar ningún cambio sobre ellas (1,40).
-
SORT: Se ordena el fichero en función del campo de
longitud 6 situado en la posición 1 (se trata del campo código de Población que
acabamos de insertar en la sentencia anterior).
-
OUTREC: Se transfiere del MASTER al TEMP2 la siguiente
información de los registros: el campo de longitud 46 situado en la posición 1
(1,46), un carácter en blanco (47:C’ ‘) y 6 espacios en blanco (6X).
El próximo día, en un nuevo post, terminaremos de ver las fichas necesarias para implementar un SPLICE en un JCL. La idea será examinar en detalle para qué sirve cada una de las sentencias incluidas en el paso 2. De ese modo, completaremos la visión global del proceso y, a partir de ese momento, ya no deberíais tener problemas a la hora de codificar vuestro propio job.
Pues nada, eso es todo por hoy. Como ya sabéis, quedáis invitados a la segunda parte del artículo. De todas formas, si no podéis esperar hasta entonces, aquí abajo podéis ir dejándome las dudas que os surjan en relación con este tema.
Saludos.
No hay comentarios:
Publicar un comentario