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

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.