viernes, 14 de enero de 2011

ICETOOL(I): SPLICE; cruce de ficheros.

Vamos a publicar una serie de articulos sobre el uso del ICETOOL.
En esta ocasión explicaremos como cruzar dos fichero mediante un JCL, con ICETOOL.

Cruce de dos ficheros usando el comando SPLICE.

Vamos a hacer el caso de cruce 1:n  (un caso particular seria el caso 1:1)

Fichero IN1:
----+----1----+----2----+
4444 1111000021 1 YYYYYYYYY
4444 1111000021 2 QQQQQQQQQ
4444 1111000021 3 VVVVVVVVV
4444 1111000021 4 CCCCCCCCC
4444 1111000021 5 ZZZZZZZZZ
4444 1111000021 6 DDDDDDDDD

Fichero IN2:
----+----1----+----2----+----3----+
000000000 CCCCCCCCC 016 1111000021 010
000000000 QQQQQQQQQ 016 1111000021 020
000000000 ZZZZZZZZZ 016 1111000021 030
000000000 YYYYYYYYY 016 1111000021 050
000000000 VVVVVVVVV 016 1111000021 050
000000000 CCCCCCCCC 016 1111000021 090
000000000 XXXXXXXXX 016 1111000021 010


JCL que realiza el cruce:

//PASO010 EXEC PGM=ICETOOL
//TOOLMSG  DD SYSOUT=*
//DFSMSG   DD SYSOUT=*
//SHOWDEF  DD SYSOUT=*
//IN1      DD DISP=SHR,
//            DSN=USER.ICETOOL.IN1
//IN2      DD DISP=SHR,
//            DSN=USER.ICETOOL.IN2
//TMP      DD DSN=&&TEMP,DISP=(MOD,PASS),
//            SPACE=(TRK,(10,10)),UNIT=SYSDA
//OUT      DD DISP=(,CATLG),SPACE=(TRK,(10,10),RLSE),
//            DSN=USER.ICETOOL.OUT
//TOOLIN   DD *
  COPY FROM(IN1) TO(TMP) USING(CTL1)
  COPY FROM(IN2) TO(TMP) USING(CTL2)
  SPLICE FROM(TMP) TO(OUT) ON(1,10,CH) ON(11,9,CH) -
  WITH(21,3) WITH(24,1) WITHALL KEEPNODUPS USING(CTL3)
/*
//CTL1CNTL DD *
  INREC BUILD=(1:5,10,11:16,9,20:15,1,24:C'BB')
//CTL2CNTL DD *
  INREC BUILD=(1:22,10,11:10,9,21:32,3,24:C'VV')
//CTL3CNTL DD *
  OUTFIL FNAMES=OUT,INCLUDE=(24,2,CH,EQ,C'VB'),OUTREC=(1,23)
/*

La idea básica para la realización del cruce consiste en usar un fichero de apoyo (un fichero temporal) que una ambos ficheros, donde la clave de cruce estará en la misma posición para todos los registros de los ficheros IN1 e IN2.
Para lograr esto utilizaremos la sentencia COPY con la ayuda del USING, que nos permitirá usar "reglas de copiado" (en este caso hemos usando INREC, pero podriamos usar otras formas como OUTREC, condicionales IFTHEN, OVERLAY, ....).

Para el IN1 tenemos :
COPY FROM(IN1) TO(TMP) USING(CTL1)
...
//CTL1CNTL DD *
  INREC BUILD=(1:5,10,11:16,9,20:15,1,24:C'BB')

----+----1----+----2----+
4444 1111000021 1 YYYYYYYYY
4444 1111000021 2 QQQQQQQQQ
4444 1111000021 3 VVVVVVVVV
4444 1111000021 4 CCCCCCCCC
4444 1111000021 5 ZZZZZZZZZ
4444 1111000021 6 DDDDDDDDD

Para el IN2 tenemos:
COPY FROM(IN1) TO(TMP) USING(CTL1)
....
//CTL2CNTL DD *
  INREC BUILD=(1:22,10,11:10,9,21:32,3,24:C'VV')

----+----1----+----2----+----3----+
000000000 CCCCCCCCC 016 1111000021 010
000000000 QQQQQQQQQ 016 1111000021 020
000000000 ZZZZZZZZZ 016 1111000021 030
000000000 YYYYYYYYY 016 1111000021 050
000000000 VVVVVVVVV 016 1111000021 050
000000000 CCCCCCCCC 016 1111000021 090
000000000 XXXXXXXXX 016 1111000021 010

El fichero temporal tendría la siguiente estructura:
----+----1----+----2----+
1111000021 YYYYYYYYY 1 BB   Este registro viene del fichero IN1
1111000021 QQQQQQQQQ 2 BB   Este registro viene del fichero IN1
1111000021 QQQQQQQQQ 030 VV   Este registro viene del fichero IN2
1111000021 VVVVVVVVV 3 BB   Este registro viene del fichero IN1
1111000021 CCCCCCCCC 4 BB   Este registro viene del fichero IN1
1111000021 CCCCCCCCC 020 VV   Este registro viene del fichero IN2
...


SPLICE FROM(TMP) TO(OUT) ON(1,10,CH) ON(11,9,CH) -
WITH(21,3) WITH(24,1) WITHALL KEEPNODUPS USING(CTL3)

IMPORTANTE: aunque acabemos de ver una estructura de fichero ordenada, la sentencia COPY no ordena. Será la sentencia SPLICE la que antes de realizar el cruce ordene por la clave especificada.

SPLICE.
Aquí nos detendremos para explicar cada una de las sentencias que acompañan a la sentencia SPLICE.

SPLICE FROM(TMP) TO(OUT) ON(1,10,CH) ON(11,9,CH) -
  WITH(21,3) WITH(24,1) WITHALL KEEPNODUPS USING(CTL3)
...
//CTL3CNTL DD *
  OUTFIL FNAMES=OUT,INCLUDE=(24,2,CH,EQ,C'VB')

  • Sentencia ON(posicion inicial, longitud, tipo).
    Esta sentencia nos permite especificar las claves de cruce. En este caso tenemos dos [ON(1,10,CH) ON(11,9,CH)]
  • Sentencia WITH(posicion inicial, longitud).
    Especificaremos aquellos campos del fichero IN2 que queramos que se vean en el fichero de salida. El resto de posiciones del fichero de salida se rellenarán con los campos del fichero IN1. En este caso hemos eligido 2 [WITH(21,3) WITH(24,1)]:

    ----+----1----+----2----+
    1111000021 CCCCCCCCC 4 B B
    1111000021 CCCCCCCCC 020 V V

Antes de seguir vamos a hacer un breve parentesis para explicar los últimos campos añadidos para el fichero IN1 'BB' y para el fichero IN2 'VV'.
Tiene dos funciones:
  1. Identificar en el fichero de salida los registros que provienen de cada fichero de entrada.
  2. Identificar los registros que se han cruzado con éxito.
    Al especificar con el WITH la primera posición del fichero IN2 [WITH(24,1)], cuando dos registros tengan la misma clave el registro de salida vendrá marcado en las dos últimas posiciones con VB.
Asi:
  1. Registros con las dos últimas posiciones BB son aquellos registros del fichero de entrada IN1 que no encontraron correspondencia en el fichero de entrada IN2
  2. Registros con las dos últimas posiciones VV son aquellos registros del fichero de entrada IN2 que no encontraron correspondencia en el fichero de entrada IN1
  3. Registros con las dos últimas posiciones VB son aquellos registros que tuvieron correspondencia.

    ----+----1----+----2----+
    1111000021 CCCCCCCCC 1 020 V B

  • Sentencia WITHALL.
    En el caso de que una clave esté más de una vez en el fichero IN2, podemos especificar WITHALL para recoger todos los registros que la contengan. Si no se especifica se quedaría con el primero.
Ejemplo:
El registro del fichero IN1:
----+----1----+----2----+
1111 1111000021 4 CCCCCCCCC

Tiene la siguiente correspondencia en el fichero IN2:
----+----1----+----2----+----3----+
000000000 CCCCCCCCC 016 1111000021 010
000000000 CCCCCCCCC 016 1111000021 090

Se almacena en el fichero temporal:
----+----1----+----2----+
1111000021 CCCCCCCCC 4 BB   Registro del fichero IN1
1111000021 CCCCCCCCC 020 VV   Registro del fichero IN2
1111000021 CCCCCCCCC 090 VV   Registro del fichero IN2

Si nosotros no especificásemos WITHALL veríamos la salida:
----+----1----+----2----+
1111000021 CCCCCCCCC 4 020 V B

Si nosotros SI especificásemos WITHALL veríamos la salida:
----+----1----+----2----+
1111000021 CCCCCCCCC 4 020 V B
1111000021 CCCCCCCCC 4 090 V B

  • Sentencia KEEPNODUPS.
    Se utiliza para mostrar en el fichero de salida, los registro del fichero IN1 cuya clave no existe en el fichero IN2.

Ejemplo:
El registro del fichero IN1:
----+----1----+----2----+
1111 1111000021 6 DDDDDDDDD

Se almacena en el fichero temporal:
----+----1----+----2----+
1111000021 DDDDDDDDD 6     BB   Registro del fichero IN1

Para nuestra clave sólo hay un registro (no encontró coincidencia en el fichero IN2).
Si nosotros no especificásemos KEEPNODUPS, no veríamos el registro en la salida.

Si lo especificamos veríamos el siguiente registro en la salida:
----+----1----+----2----+
1111000021 DDDDDDDDD 6     B B

  • Sentencia USING.
    También fue usada cuando copiábamos los ficheros al temporal. Podríamos decir que son unas "reglas de copiado" para definir el fichero de salida. En este caso:
    • OUTFIL, para generar el fichero de salida OUT.
    • INCLUDE, para seleccionar aquellos registros que se cruzaron.
    • OUTREC, para eliminar las dos últimas posiciones de trabajo.

Esto es una manera sencilla y rapida de hacer un cruce de dos ficheros.
Es importante asegurarse de que el fichero de entrada no tenga duplicados por clave, es decir, es un cruce 1 a n.

Para terminar, os dejo para descargar el JCL, los ficheros de entrada, y el fichero de salida:
JCL con ICETOOL.
Fichero IN1.
Fichero IN2.
Fichero OUT.

14 comentarios:

Anónimo dijo...

Muy buena la explicaciòn de ICETOOL, gracias.
Ernesto Nunes (Caracas,Venezuela)

Anónimo dijo...

Es una explicación clariiisssima, mil gracias!

Anónimo dijo...

Muchas gracias, me está resultando bastante util y está muy bien explicado.

Tallian dijo...

Gracias a vosotros!!

Anónimo dijo...

Excelente (Leo Mercado MEX)¡¡¡

PeterDark dijo...

Muy buena explicación, es útil si no se quiere hacer el matching por programa. Gracias!

Anónimo dijo...

Y si queremos realizar un cruce de los dos ficheros de forma que por cada registro del primer fichero tuvieramos todos los ficheros del segundo,

Anónimo dijo...

Muy buen articulo! Yo tengo un cruce de n:n, necesito sacar cada reg comun del primero con todos los del segundo: primer fichero -> c1a c1b c1c , segundo fichero c1y c1z --->resultado: c1ac1y c1ac1z
c1bc1y c1bc1z
c1cc1y c1cc1z

Anónimo dijo...

Buenos días, me dice que tengo un FLUSH en el paso010. ¿Cómo puede ser? ¿A qué se puede deber?

Muchas gracias

EFRAIN dijo...

Hola.

A la hora de ejecutar el job para escribir los registros en el archivo temporar, al final solo escribr los registros del archivo IN2, en el spool veo que si se ejectan las dos instrucciones CTL1CNTL y CTL2CNTL pero al final en el archivo temporal solo copia lo de CTL2CNTL.

¿Alguien puede ayudarme?

Da antemano gracias.

Saludos.

angel martinez dijo...
Este comentario ha sido eliminado por el autor.
angel martinez dijo...

¿Se podria cambiar el cruce para que sea 1 a 1?

Tallian dijo...

Hola Angel. El cruce vale también como 1-1. En este caso el fichero 2 tenía claves repetidas, pero si el tuyo no la tiene, valdría el mismo código.
Te sobraría el WITHALL KEEPNODUPS

angel martinez dijo...

Cierto, me explique mal una disculpa, lo que pasa es que quiero realizar un match donde los registros con llaves duplicadas se informen como si no hicieran match.

Ejemplo:

El registró del fichero IN1:
----+----1----+----2----+
111111110000214CCCCCCCCC

Tiene la siguiente correspondencia en el fichero IN2:
----+----1----+----2----+----3----+
000000000CCCCCCCCC0161111000021010
000000000CCCCCCCCC0161111000021090

Se almacena en el fichero temporal:
----+----1----+----2----+
1111000021CCCCCCCCC4 BB Registro del fichero IN1
1111000021CCCCCCCCC 020VV Registro del fichero IN2
1111000021CCCCCCCCC 090VV Registro del fichero IN2

Salida:
----+----1----+----2----+
1111000021CCCCCCCCC4020VB Registro en el fichero IN1 e IN2 1111000021CCCCCCCCC4090VV Registro en el fichero IN2

Las llaves duplicadas pueden estar en los dos archivos.

Gracias de antemano.