lunes, 9 de noviembre de 2015

¿Cómo recuperar queries en QMF?

Hace algunas semanas estuvimos viendo cómo se puede almacenar una query en la base de datos de QMF. Una vez que tenemos dicha información a salvo, hoy vamos a centrarnos en revisar cuáles son los comandos que tenemos disponibles para poder recuperar dichas querys de la base de datos.

En su día ya estuvimos viendo la instrucción SAVE de QMF, que nos permitía guardar cualquier tipo de código que tuviésemos escrito en el menú DRAW. Junto a ella, como veremos a continuación, tenemos otros otros dos comandos que nos van a venir muy bien a la hora de reutilizar nuestras queries de uso más frecuente. Se trata de DISPLAY QUERY y de LIST QUERIES.

¿Cómo recuperar una query en QMF?


Una vez almacenada la información, la siguiente cuestión que se nos plantearía es cómo recuperar la query en el momento en el que lo deseemos. Obviamente, no tendría mucho sentido almacenar el código si no pensamos usarlo nunca más con posterioridad.

En este entorno, para realizar la acción de recuperar la query en QMF disponemos del comando DISPLAY. Para poder usarlo, en primer lugar tendremos que posicionarnos en la ventana 6=DRAW de la herramienta QMF, tal y como hicimos a la hora de guardar el código.

Una vez aquí, en la línea COMMAND tendremos que incluir el comando DISPLAY QUERY.

COMMAND ===> DISPLAY QUERY EJEMPLO

Pulsamos INTRO y se nos deplegará la siguiente ventana.


Como se puede apreciar, se trata del mismo código que previamente habíamos almacenado con el comando SAVE. Una vez recuperada, esta declaración ya se podría ejecutar del mismo modo que se haría con cualquier otra query de QMF.

Listar todas las queries almacenadas en QMF


Imaginaos que llega un momento en el que tenéis almacenadas 50 queries en vuestro QMF y, por la razón que sea, un cliente os pide que obtengáis de nuevo un informe cuya query lanzásteis hace más de un año. Lo más probable es que no os acordéis del nombre con el que la guardásteis. Entonces, ¿cómo podríais acceder de nuevo a ella?

Para estos casos vamos a usar el comando LIST, que nos mostrará un listado de todas las queries que nuestro usuario tiene almacenadas en la base de datos de QMF. De nuevo, para poder usarlo, en primer lugar tendremos que posicionarnos en la ventana 6=DRAW de la herramienta QMF.

Una vez aquí, en la línea COMMAND tendremos que incluir el comando LIST QUERIES.

COMMAND ===> LIST QUERIES

Pulsamos INTRO y se nos deplegará la siguiente ventana.








Como vemos, en esta pantalla aparecen las queries que previamente he almacenado en QMF con mi usuario.

A continuación, si queremos recuperar el código de alguno de los objetos SQL listados, lo único que tendremos que hacer es usar el comando DISPLAY en la columna ACTION. De este modo, se recuperará el contenido de la query de la misma forma que con el comando DISPLAY QUERY que hemos examinado anteriormente.

                                     --------Dates--------
Action   Name               Owner    Modified   Last Used
                                                         
DISPLAY  EJEMPLO            JJ00917  2015-10-06 2015-10-07


Esta sería el método estándar para recuperar una query de nuestra base de datos de QMF siempre que no recordemos el nombre con el que la almacenamos en su día.

Almacenar y recuperar queries en QMF


En principio, con los comandos revisados, ya podríamos operar de una manera básica con la base de datos de QMF. Las instrucciones SAVE, DISPLAY y LIST nos permitirán almacenar las queries que vayamos creando y recuperarlas siempre que tengamos necesidad de ellas (independientemente de que nos encontremos ante un tratamiento con la instrucción SELECT, con UPDATE, con INSERT o con DELETE).

Por supuesto, existen más comandos QMF que los aquí mencionados, pero con estas 3 instrucciones ya podremos sobrevivir en el entorno. En un futuro, en un nuevo post, intentaré esbozar una visión global de cuáles son todos los comandos disponibles para esta herramienta.

Aunque siempre habrá queries que sólo queramos usar una vez y que puedan ser desechadas tras su uso, lo importante es que tengamos la posibilidad de reutilizar fácilmente las queries que deban ser ejecutadas periódicamente. Esa función podrá ser realizada de forma eficiente con las instrucciones QMF revisadas hoy.



En principio, siguiendo los pasos aquí comentados no deberíais tener problemas a la hora de trabajar en el entorno. De todas formas, cualquier problema o duda que os surja, ya sabéis que podéis dejármela abajo en los comentarios. Intentaré contestaros lo antes posible.

Y eso es todo por hoy. Espero que con lo comentado en el post tengáis suficiente para moveros por QMF y que al menos os sirva para poder almacenar (y recuperar posteriormente) vuestras queries más importantes.

Saludos.

lunes, 2 de noviembre de 2015

¿Cómo almacenar queries en QMF?

En ocasiones, tras utilizar una determinada query en QMF, nos damos cuenta de que vamos a tener que emplearla más veces en el futuro. En condiciones normales, al abandonar la sesión de la herramienta QMF perderíamos el código introducido y, por tanto, la próxima vez que quisiéramos ejecutarla tendríamos que volver a teclear la query completa. Sin embargo, existe una forma de almacenar este código para poder recuperarlo en el futuro.

Ejecución múltiple de queries en QMF


Si necesitamos emplear una determinada query en múltiples ocasiones a lo largo del tiempo, no será necesario que introduzcamos su código cada vez que tengamos que recurrir a ella. La herramienta QMF nos da la opción de almacenar el código de dicha query, de manera que podamos recuperarlo siempre que lo precisemos.

Para explicar esto, prefiero que lo veamos con un ejemplo. Supongamos, por tanto, que hemos creado una determinada query SQL (a petición de nuestro cliente, por supuesto) y que ya la hemos ejecutado y hemos obtenido la información que nos habían solicitado.


La query en cuestión sería la siguiente, donde se realizaría la extracción de todas las poblaciones que pertenezcan a la provincia de Madrid y que hayan sido dadas de alta en el sistema en el año 2014 o en algún ejercicio posterior.

SELECT * FROM JJDB22.JJLOCAT0        
  WHERE JJGE_CO_INTERN = '28'        
    AND JJCA_FX_ALTSIS >= '2014-01-01'


Una vez ejecutada la query, los resultados mostrados serían los siguientes, donde se visualizaría el código y la descripción de cada población (entre otros datos).

    JJTU    JJCA    JJCA    JJCA    JJCA           
     CO      CO      CO      CO      NO            
   INTERN  INTERN  2SCLOC  3SCLOC  PBLSIT          
---------  ------  ------  ------  -----------------
    43277       0                  COLMENAR VIEJO  
    43277       1  CTO     1       COLMENAR VIEJO  
    44590       0                  COLMENAR VIEJO  
    44590       1  DIV2    0       COLMENAR VIEJO  
    44590       2  DV00    2       COLMENAR VIEJO  
    44590       3  CTO     1       COLMENAR VIEJO  
    47909       0                  MADRID          
    57746       0                  MADRID          
    91957       0                  MADRID          
    91966       0                  ALCOBENDAS      
    91966       1  CTO     1       ALCOBENDAS        


Se trata únicamente de la primera página extraída por QMF ya que, obviamente, para este ejemplo no merece la pena mostrar más datos del listado.

¿Cómo almacenar una query en QMF?


Normalmente, ejecutaremos la query sobre la tabla DB2, obtendremos los resultados y desecharemos el código con posterioridad. Sin embargo, en el caso de que concluyamos que este proceso nos puede resultar útil en el futuro o de que sospechemos que el cliente nos puede volver a pedir el mismo informe más adelante, entonces lo óptimo sería almacenarnos la declaración para no tener que volver a teclearla más veces.

Para poder guardarnos una query sobre DB2, en primer lugar tendremos que posicionarnos en la ventana 6=DRAW de la herramienta QMF.





Una vez aquí, en la línea COMMAND tendremos que insertar el comando SAVE.

COMMAND ===> SAVE

Pulsamos INTRO y se nos deplegará la siguiente ventana.



En esta ventana tenemos 3 apartados que tendremos que rellenar antes de confirmar la operación.

1º) NAME: Aquí simplemente tendremos que indicar el nombre con el que deseamos que la query con SELECT (o con cualquier otra instrucción) quede almacenada en QMF.

2º) CONFIRM: Aquí tendremos que indicar YES si queremos que, en el futuro, el sistema nos pida confirmación cada vez que queramos modificar esta query en el almacén de QMF.

3º) SHARE: Si indicamos YES en esta opción, entonces la query que almacenemos en QMF podrá ser recuperada por cualquier otro usuario que conozca el nombre de la misma.

Una vez que rellenemos estos datos y pulsemos INTRO, en QMF nos aparecerá el siguiente mensaje, donde se nos confirma el guardado del objeto con el nombre de nuestro usuario seguido del nombre elegido para la query (en la ventana anterior).

OK, QUERY was saved as JJ00917.EJEMPLO in the database.


En estos momentos, nuestra query ya quedaría almacenada en la base de datos de QMF y ya estaría disponible para ser recuperada fácilmente en el futuro.



Una vez visto el comando con el que podemos salvar queries en QMF, en un futuro post pasaremos a examinar las instrucciones que nos van a permitir recuperar esas queries almacenadas. Tened en cuenta que con todo esto no pretendo hacer una revisión exhaustiva de los comandos QMF, sino simplemente dar un repaso a los conceptos más básicos que nos van a permitir sobrellevar nuestro día a día en el cliente.

Y eso es todo por hoy. Como siempre, espero que con la explicación os haya quedado claro cómo se pueden almacenar queries en QMF. En caso contrario, ya sabéis que podéis dejarme vuestras dudas aquí abajo...

Saludos.

lunes, 26 de octubre de 2015

Comando COMPUTE para Cobol

Como en todos los lenguajes, en Cobol también disponemos de un comando específico que nos permite realizar operaciones matemáticas entre operandos. Eso sí, debido a que nuestro lenguaje no está pensado para su utilización en entornos científicos, en las rutinas que elaboremos sólo podremos incluir operaciones aritméticas sencillas.

Ejecución de operaciones matemáticas en Cobol


Seguro que, en más de una ocasión, os habéis encontrado con una situación en la que el algoritmo de una determinada funcionalidad os ha obligado a implementar alguna operación matemática. Para acometer tareas de este tipo, en lenguaje Cobol disponemos de los comandos ADD, SUBTRACT, MULTIPLY y DIVIDE (sumar, restar, multiplicar y dividir).

Pero, si queremos implementar fórmulas algo más complejas, podemos recurrir al comando COMPUTE. Esta función nos permitiría incluir, en una misma declaración, la ejecución de múltiples operaciones sobre operandos diversos. De este modo, podremos realizar sumas, restas, multiplicaciones y divisiones en la misma sentencia.


Como vemos, se trata de un comando bastante estándar. De hecho, hay varios lenguajes de programación en los que esta función se denomina del mismo modo: COMPUTE. Sin ir más lejos, así ocurre en Natural ADABAS, otro de los lenguajes de los que solemos hablar de vez en cuando en el blog.

¿Cómo se implementa una sentencia COMPUTE?


A continuación vamos a ver un ejemplo de cómo se debería implementar la sentencia COMPUTE dentro de un párrafo de Cobol. Obviamente, el número de combinaciones para esta función es muy elevado pero, para facilitar su explicación, centrémonos en la siguiente fórmula modelo que se compone de 3 operadores y de 8 variables.

DATA DIVISION.
WORKING-STORAGE SECTION.

01 W-PTOS-CALCULADOS           PIC 9(5).

01 W-DISTANCIAS-ABS.                                   
  05 W-REGL-NU-COORDX-DESDE    PIC  9(5)     VALUE ZEROES.
  05 W-REGL-NU-COORDY-DESDE    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDX-DESDE    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDY-DESDE    PIC  9(5)     VALUE ZEROES.

  05 W-REGL-NU-COORDX-HASTA    PIC  9(5)     VALUE ZEROES.
  05 W-REGL-NU-COORDY-HASTA    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDX-HASTA    PIC  9(5)     VALUE ZEROES.
  05 W-PTCO-NU-COORDY-HASTA    PIC  9(5)     VALUE ZEROES.


...

PROCEDURE DIVISION.

COMPUTE  W-PTOS-CALCULADOS  =    
   (W-REGL-NU-COORDX-HASTA -     
    W-REGL-NU-COORDX-DESDE + 1 ) *
   (W-REGL-NU-COORDY-HASTA -     
    W-REGL-NU-COORDY-DESDE + 1 ) *
   (W-PTCO-NU-COORDX-HASTA -     
    W-PTCO-NU-COORDX-DESDE + 1 ) *
   (W-PTCO-NU-COORDY-HASTA -     
    W-PTCO-NU-COORDY-DESDE + 1 ).   


Como se aprecia, en la declaración anterior se están usando 8 variables y 3 operadores aritméticos: suma, resta y multiplicación. De este modo nos evitamos tener que emplear 3 sentencias distintas con los comandos ADD, SUBTRACT y MULTIPLY y, al mismo tiempo, nos ahorramos la definición de algunas variables auxiliares que hubiésemos tenido que utilizar en el caso de no recurrir al comando COMPUTE.


Por lo que respecta a la fórmula en sí misma, entiendo que es muy sencilla y que no hace falta recurrir a ninguna explicación adicional de la misma. Básicamente, se están calculando las diferencias entre varias coordenadas y multiplicando dichas distancias entre sí para obtener un valor denominado "Puntos Calculados" (variable que, una vez visto el ejemplo, ya no tiene interés para nosotros y que se usará posteriormente en el algoritmo del programa Cobol CICS).

Aprendiendo a utilizar el comando COMPUTE


Una vez visto cómo hemos realizado la declaración en nuestro ejemplo, no deberíais tener problemas a la hora de extrapolar su empleo a vuestros propios programas. Se trata de un comando estándar cuya utilización es bastante intuitiva y, según mi experiencia, no suele causar demasiadas dificultades a los programadores principiantes.

Por si acaso, y teniendo en cuenta que un ejemplo práctico vale más que 1.000 palabras de teoría, a continuación paso a incluir algunas sentencias más con posibles usos del comando. A partir de ellos, se pueden elaborar otras 1.000 variantes diferentes, de manera que no vamos a tener problemas para encontrar la opción que encaje con el que requiera nuestro algoritmo.

COMPUTE W-TOTAL-1 = W-OPERANDOS-1 + W-OPERANDOS-2

COMPUTE W-TOTAL-2 = W-OPERANDOR-1 - W-OPERANDOR-2

COMPUTE W-TOTAL-3 = W-OPERANDOM-1 * W-OPERANDOM-2

COMPUTE W-TOTAL-4 = W-OPERANDOD-1 / W-OPERANDOD-2

COMPUTE W-TOTAL-5 = (W-OPERANDOSD-1 + W-OPERANDOSD-2) / (W-OPERANDOSD-3 - W-OPERANDOSD-4)

COMPUTE W-TOTAL-6 = (W-OPERANDODM-1 / W-OPERANDODM-2) * (W-OPERANDODM-3 / W-OPERANDODM-4)

COMPUTE W-TOTAL-7 = (W-OPERANDORD-1 - W-OPERANDORD-2) / W-OPERANDORD-3

COMPUTE W-TOTAL-8 = (W-OPERANDOSM-1 + 1) * (W-OPERANDOSM-2 / W-OPERANDOSM-3) * ((W-OPERANDOSM-4 - W-OPERANDOSM-5) / W-OPERANDOSM-6)

Como vemos, las construcciones con COMPUTE se pueden ir incrementando de dificultad de forma indefinida. Esto nos va a facilitar la incorporación de la complejidad requerida a nuestras fórmulas, siempre y cuando no nos salgamos del catálogo de operaciones aritméticas básicas. En mi propia experiencia, el comando COMPUTE es más que suficiente para implementar la mayoría de las fórmulas requeridas en los algoritmos de los programas Cobol CICS DB2.


En definitiva, tenemos que considerar al COMPUTE como una sentencia de elaboración de fórmulas aritméticas que nos va a permitir ahorrar tiempo y código a la hora de desarrollar. Por un lado, su uso nos permitirá sustituir a los comandos ADD, SUBTRAC, MULTIPLY y DIVIDE; por otro lado, reduciremos el número de variables auxiliares precisadas para operar.

Y eso es todo por hoy. Espero que lo comentado os sirva para resolver todas las dudas que tengáis acerca del comando COMPUTE y que os facilite vuestra labor con el cliente. De todas formas, ya sabéis que podéis dejarme cualquier comentario aquí abajo y os lo responderé lo antes posible...

Saludos.

lunes, 19 de octubre de 2015

Visualizar Fichero comprimido en ISPF

En general, la visualización del contenido de un fichero secuencial con formato estándar no suele tener ninguna complejidad asociada. Sin embargo, se requiere algo más de esfuerzo para poder observar los ficheros cuyos registros contienen campos comprimidos. A continuación, vamos a ver cómo hacerlo.

Ficheros secuenciales con datos empaquetados


Cuando trabajamos con ficheros secuenciales, lo normal es que los registros de los mismos vayan con formato numérico o alfanumérico no comprimido, ya que es el tipo que suele ser más fácil de manejar. Sin embargo, en ocasiones, la necesidad de ahorro de espacio nos puede obligar a trabajar con ficheros con datos en formato empaquetado (COMP-3). La visualización de la información no se realizará del mismo modo en un caso o en otro.

Para tener clara esta diferencia podemos mostrar unos ejemplos. Vamos a acceder al contenido de los ficheros JJPR.UNLOAD.X0005X.POBL y JJPR.UNLOAD.X0005X.POBL2. El primero de ellos está en formato alfanumérico y el segundo contiene algunos campos con formato comprimido COMP-3.



Los registros del fichero alfanumérico son los siguientes (JJPR.UNLOAD.X0005X.POBL).

=COLS> ----+----1----+----2----+----3----+----4    
****** ***************************** Top of Data ***
000001 A-000020-MADRID.................MAD00100    
000002 B-000019-CIUDAD REAL............CRE00200    
000003 A-000018-BARCELONA..............BAR00300    
000004 A-000017-VALENCIA...............VAL00400    
000005 A-000015-ZARAGOZA...............ZAR00600    
000006 B-000014-CASTELLON..............CAS00700    
000007 B-000012-GRANADA................GRA00900    
000008 B-000011-TOLEDO.................TOL01000    
000009 B-000010-SEGOVIA................SEG01100    
000010 B-000002-ALMERIA................ALM01300    
000011 B-000004-SANTANDER..............SAN01500    
000012 B-000005-TARRAGONA..............TAR01600    
000013 B-000006-BADAJOZ................BAD01700    
000014 B-000007-SALAMANCA..............SAL01800    
000015 B-000008-BURGOS.................BUR01900    
=COLS> ----+----1----+----2----+----3----+----4      
****** **************************** Bottom of Data ***


En cambio, el contenido del fichero empaquetado tiene el siguiente aspecto (JJPR.UNLOAD.X0005X.POBL2).

=COLS> ----+----1----+----2----+----3----+--       
****** ***************************** Top of Data ***
000001 A-    -MADRID.................MAD
000002 B-   æ-CIUDAD REAL............CRE
000003 A-   ð-BARCELONA..............BAR
000004 A-   @-VALENCIA...............VAL 
000005 A-   *-ZARAGOZA...............ZAR  -
000006 B-   <-CASTELLON..............CAS  ø
000007 B-    -GRANADA................GRA  °
000008 B-    -TOLEDO.................TOL
000009 B-    -SEGOVIA................SEG
000010 B-    -ALMERIA................ALM
000011 B-   <-SANTANDER..............SAN  &
000012 B-   *-TARRAGONA..............TAR  -
000013 B-   %-BADAJOZ................BAD  ø
000014 B-   @-SALAMANCA..............SAL  Ø
000015 B-   ð-BURGOS.................BUR  °
=COLS> ----+----1----+----2----+----3----+--         
****** **************************** Bottom of Data *** 


Como vemos, los registros del primer fichero son perfectamente legibles sin ninguna acción adicional. Sin embargo, el contenido del segundo fichero aparece con caracteres extraños (formato empaquetado), haciendo imposible identificar los códigos almacenados en sus registros.


¿Cómo visualizar un fichero comprimido?


A continuación, vamos a ver qué es lo que debería hacerse para visualizar el contenido de un fichero comprimido. Se trata de algo muy sencillo pero que, si no conocemos, nos provocará bastantes quebraderos de cabeza al enfrentarnos con campos COMP-3.

Lo que debemos hacer es lo siguiente. En primer lugar, realizamos la apertura del fichero desde la herramienta ISPF. Posteriormente, nos situamos en la línea de comandos COMMAND e introducimos la sentencia HEX ON (activar hexadecimal).

EDIT       JJPR.UNLOAD.X0005X.POBL2         
Command ===> HEX ON                                
=COLS> ----+----1----+----2----+----3----+--    


A continuación, pulsamos INTRO y la utilidad pasará a mostrarnos el contenido de los campos comprimidos en COMP-3.

=COLS> ----+----1----+----2----+----3----+--       
****** ***************************** Top of Data ***
000001 A-    -MADRID.................MAD      
       C600006DCCDCC44444444444444444DCC0010      
       10002C0414994BBBBBBBBBBBBBBBBB414000C      
---------------------------------------------------
000002 B-   æ-CIUDAD REAL............CRE      
       C600096CCECCC4DCCD444444444444CDC0020      
       20001C039441409513BBBBBBBBBBBB395000C      
---------------------------------------------------
000003 A-   ð-BARCELONA..............BAR      
       C600086CCDCCDDDC44444444444444CCD0030      
       10001C0219353651BBBBBBBBBBBBBB219000C      
---------------------------------------------------
000004 A-   @-VALENCIA...............VAL        
       C600076ECDCDCCC444444444444444ECD0040      
       10001C051355391BBBBBBBBBBBBBBB513000C      
000005 A-   *-ZARAGOZA...............ZAR  -       
       C600056ECDCCDEC444444444444444ECD0060       
       10001C091917691BBBBBBBBBBBBBBB919000C       
----------------------------------------------------
000006 B-   <-CASTELLON..............CAS  ø       
       C600046CCEECDDDD44444444444444CCE0070       
       20001C0312353365BBBBBBBBBBBBBB312000C       
----------------------------------------------------
000007 B-    -GRANADA................GRA  °       
       C600026CDCDCCC4444444444444444CDC0090       
       20001C07915141BBBBBBBBBBBBBBBB791000C       
----------------------------------------------------
000008 B-    -TOLEDO.................TOL       
       C600016EDDCCD44444444444444444EDD0000       
       20001C0363546BBBBBBBBBBBBBBBBB363010C       
----------------------------------------------------
000009 B-    -SEGOVIA................SEG       
       C600006ECCDECC4444444444444444ECC0010       
       20001C02576591BBBBBBBBBBBBBBBB257010C       
----------------------------------------------------
000010 B-    -ALMERIA................ALM       
       C600026CDDCDCC4444444444444444CDD0030       
       20000C01345991BBBBBBBBBBBBBBBB134010C       
----------------------------------------------------
000011 B-   <-SANTANDER..............SAN  &       
       C600046ECDECDCCD44444444444444ECD0050       
       20000C0215315459BBBBBBBBBBBBBB215010C       
----------------------------------------------------
000012 B-   *-TARRAGONA..............TAR  -       
       C600056ECDDCCDDC44444444444444ECD0060       
       20000C0319917651BBBBBBBBBBBBBB319010C       
----------------------------------------------------
000013 B-   %-BADAJOZ................BAD  ø       
       C600066CCCCDDE4444444444444444CCC0070       
       20000C02141169BBBBBBBBBBBBBBBB214010C       
----------------------------------------------------
000014 B-   @-SALAMANCA..............SAL  Ø       
       C600076ECDCDCDCC44444444444444ECD0080       
       20000C0213141531BBBBBBBBBBBBBB213010C       
----------------------------------------------------
000015 B-   ð-BURGOS.................BUR  °       
       C600086CEDCDE44444444444444444CED0090       
       20000C0249762BBBBBBBBBBBBBBBBB249010C       
----------------------------------------------------
****** **************************** Bottom of Data ***
=COLS> ----+----1----+----2----+----3----+--


Como vemos, ahora bajo cada registro comprimido original se muestran otros dos registros adicionales. En ellos aparece decodificada la información correspondiente a los campos hexadecimales.


Decodificación de campos hexadecimales

  
Por ejemplo, este es el registro original (no comprimido) correspondiente a MADRID.

000001 A-000020-MADRID.................MAD00100     

Ahora se corresponde con estos 3 registros.

----------------------------------------------------
000001 A-    -MADRID.................MAD      
       C600006DCCDCC44444444444444444DCC0010      
       10002C0414994BBBBBBBBBBBBBBBBB414000C 

----------------------------------------------------


He marcado en rojo la decodificación realizada de los dos campos hexadecimales que contienen los registros de este fichero. El primero es el código interno, 000020, y el segundo es el código externo, 00100. El código interno aparece decodificado como:

0000
002C

Si leemos las líneas anteriores ordenadas de arriba a abajo y de izquierda a derecha, entonces el campo se correspondería con el siguiente número:

0000020C

Donde los 6 dígitos marcados se corresponden con el código interno original, en formato no comprimido 000020.


Del mismo modo, el código externo aparece decodificado como:

0010
000C

Si los leemos ordenados de arriba a abajo y de izquierda a derecha se corresponderían con el siguiente número:

0000100C

Al igual que en el caso anterior, los 5 dígitos marcados se corresponden con el código externo original, en formato no comprimido 00100.

Visualización de ficheros comprimidos en ISPF


Por tanto, podemos ver como el uso del comando HEX ON nos permite acceder a la decodificación numérica de los campos comprimidos de los registros afectados. Con esta sencilla operación evitaremos perder mucho tiempo tratando de descifrar el contenido de los campos hexadecimales.


Si ya conocíais esta forma de visualizar los ficheros comprimidos desde ISPF, entonces este post os habrá parecido superfluo. Sin embargo, debéis tener en cuenta que hay muchos programadores principiantes que, un buen día, se enfrentan con su primer fichero comprimido y en ese momento no saben cómo proceder para leer los datos de los registros. A ellos está dedicado este texto.

Pues nada, eso es todo por hoy. Espero que lo comentado os haya servido para aprender algo nuevo y, lo más importante, que os valga para agilizar vuestro trabajo cotidiano.

Saludos.

lunes, 12 de octubre de 2015

Buscar varios Ficheros a la vez en ISPF (y 2)

Hace algunas semanas comenzamos a ver cómo se podían buscar (y editar) varios ficheros a la vez desde la herramienta ISPF. Se trata de una opción que nos puede facilitar mucho las cosas en el día a día, ya que no es lo mismo poder realizar una búsqueda múltiple que tener que ir accediendo a todos los ficheros uno a uno.

En la primera parte del post vimos un ejemplo de búsqueda simple y, además, hicimos un esbozo de qué es lo que se entiende por editar varios ficheros a la vez (ver post Buscar varios ficheros a la vez en ISPF - 1). Hoy vamos a entrar en detalle y procederemos a examinar los dos casos modelo que cubrirán el 90% de nuestras necesidades a este respecto.

¿Cómo podemos editar varios ficheros a la vez en ISPF?


El caso de búsqueda simple que mostramos anteriormente nos sirve si queremos acceder a un único fichero y si, además, conocemos el nombre del mismo. Pero, ¿qué pasaría si quisiéramos visualizar el contenido de varios ficheros (cuyos nombres tengan alguna cadena de caracteres en común)? ¿Y qué pasaría si no conociésemos el nombre completo del fichero buscado?

Caso 1: Editar varios ficheros a la vez en ISPF


Imaginemos, en primer lugar, que en nuestra aplicación queremos ir viendo el contenido de varios ficheros generados por un determinado proceso que realiza la tramitación de Tarjetas (TARJ). Esta fase JCL genera múltiples datasets con distintos nombres y sabemos que en todos ellos va a figurar la cadena de texto TARJ.

Entonces, en vez de ir poniendo el nombre de cada uno de los ficheros y accediendo a su contenido uno a uno, lo óptimo sería introducir la cadena de texto común en el campo DSNAME LEVEL de la herramienta ISPF. En nuestro caso, podríamos incluir el texto ASTR.A801.*.**.*TARJ*.



Al pulsar INTRO se nos van a mostrar todos los ficheros cuyo nombre cumpla con las condiciones introducidas anteriormente.



Como vemos, se han obtenido todos los datasets que comienzan por “ASTR.A801”  y que tienen la cadena de texto “TARJ” en alguna posición de su denominación. En total, tenemos 7 ficheros y nos hemos ahorrado el trabajo de tener que ir editando cada uno de ellos por separado.

Caso 2: Editar un fichero sin conocer el nombre exacto


Imaginemos ahora, en segundo lugar, que queremos editar un fichero del que no recordamos su nombre exacto. Sabemos que se trata de un fichero de Incidencias y que en el sexto bloque de su denominación figura la cadena de texto “INCI”. De manera análoga al primer caso, aquí podríamos incluir en el campo DSNAME LEVEL del ISPF el texto ASTR.A801*.*.*.*.INCI*.


Al pulsar INTRO se nos va a mostrar el fichero (o ficheros) cuyo nombre cumple con las condiciones introducidas anteriormente.


Como se observa, en la pantalla han aparecido todos los datasets que comienzan por “ASTR.A801”  y que tienen la cadena de texto “INCI” en el sexto bloque de su denominación. En total, tenemos 7 ficheros. Sin lugar a dudas, el fichero de Incidencias que buscamos será uno de ellos y lo hemos encontrado sin necesidad de recordar su nombre completo.

Una vez visto estos dos ejemplos, creo que no hace falta hacer mucho más hincapié en el considerable ahorro de tiempo que supondrá el uso de las búsquedas múltiples. Y lo mejor de todo es que el procedimiento es bastante fácil de recordar, siempre y cuando no hayan transcurrido más de 5 años desde la última vez que lo pusimos en práctica (como le pasó a mi compañero)…


Conclusiones acerca de la edición múltiple de ficheros del ISPF


Si estamos buscando un fichero determinado y nos sabemos su denominación exacta, en general haremos uso de la edición simple del Data Set List Utility de la utilidad ISPF. En este caso, bastará con introducir el nombre completo en el campo DSNAME LEVEL y la herramienta nos mostrará el fichero indicado.

Sin embargo, en los casos en que queramos editar varios ficheros a la vez (o si simplemente no recordamos el nombre completo de nuestro dataset) no nos quedará más remedio que hacer uso de la edición múltiple de la utilidad. Esto se conseguirá introduciendo el carácter “*” (asterisco) en las posiciones requeridas del texto introducido en el campo DSNAME LEVEL, tal y como se ha explicado en los ejemplos comentados a lo largo del artículo.

Obviamente, se trata de una funcionalidad muy simple y con la que se obtiene un considerable ahorro de tiempo a largo plazo. Si no sabíais hacer la edición múltiple, lo más probable es que, una vez leído este post, probéis a lanzar la búsqueda en ISPF por primera vez y ya nunca más tengáis necesidad de volver a consultar cómo se hace. Las cosas sencillas no suelen olvidarse con facilidad…


Os comento esto porque fue precisamente lo que me sucedió a mí. Al principio, cuando empecé a programar en Cobol y a trabajar en el entorno ISPF, no sabía cómo hacer una búsqueda múltiple de ficheros y tuve que pedir ayuda a un compañero. Desde entonces, ya no he tenido que volver a preguntarlo nunca más (y ahora incluso ya está escrito en el blog).

Pues nada, no queda mucho más que contar con respecto a la utilidad Data Set List Utility de ISPF. Si tenéis alguna duda al respecto, ya sabéis que podéis dejarla en el apartado de comentarios y trataré de responderos lo antes posible.

Saludos.

lunes, 5 de octubre de 2015

Buscar varios Ficheros a la vez en ISPF (1)

Del mismo modo que todo el mundo sabe cómo buscar un fichero secuencial en el entorno ISPF, esta herramienta también nos ofrece la posibilidad de buscar varios ficheros a la vez. Y lo que es mejor, ni siquiera tendremos que conocer el nombre completo de los datsets para poder ejecutar dicha búsqueda.

Búsqueda múltiple de ficheros en ISPF


En general, cuando accedemos a la opción Data SetList Utility de ISPF, lo hacemos con la idea de buscar un fichero concreto (o una librería específica) y visualizar su contenido. Sin embargo, esta utilidad también nos permite lanzar una búsqueda múltiple de varios ficheros, siempre y cuando compartan una determinada cadena de caracteres.

Esto nos va a permitir, por un lado, listar varios ficheros (cuyas denominaciones tengan un fragmento en común) sin necesidad de ir introduciendo uno a uno el nombre de todos ellos. Y, por otro lado, nos va a dar la posibilidad de buscar un fichero a partir de una cadena de texto sin necesidad de tener que recordar su nombre exacto.


Esta funcionalidad es sencilla y nos puede parecer una nimiedad. Y en realidad lo es. Pero probablemente no sepamos cómo hacerlo si somos programadores novatos o si hace muchos años que no programamos con lenguaje Cobol (o que no usamos ISPF).

De hecho, esto fue lo que le pasó hace unas semanas a un compañero. A pesar de tener más de 5 años de experiencia trabajando con Host, el problema es que llevaba otros 5 años sin tocar ISPF y, por tanto, cuando llegó aquí e intentó hacer una búsqueda múltiple, se quedó en blanco. Aunque parezca mentira, todo conocimiento se va desvaneciendo con el paso del tiempo si no se refresca a menudo.

Utilidad Data Set List Utility de ISPF


Cuando entramos en la ventana Data Set List Utility de ISPF (opción 3.4 para los amigos), normalmente lo hacemos con la idea de acceder a un determinado fichero (o librería) y ver su contenido. Por tanto, en estos casos ya nos sabemos el nombre de dicho dataset y lo único que tenemos que hacer es especificar su nombre en la utilidad.

Por ejemplo, si queremos buscar el fichero ASPR.V7R01.JJST.FUENTES.BACKUP, pondremos el nombre en el campo DSNAME LEVEL en la utilidad.


A continuación, pulsaremos INTRO y la herramienta nos mostrará el fichero (o librería) que coincida con dicha denominación.



Este es el funcionamiento estándar y no tiene mucha más historia. Una vez se nos haya mostrado el fichero encontrado, no deberíamos tener problemas en acceder a su contenido y ver los registros (o los objetos) que se encuentren en su interior.

Una vez examinada la búsqueda simple, el próximo día (en un nuevo post) procederemos a detallar en qué consiste la búsqueda múltiple de ficheros. Además, mostraremos ejemplos de los casos más comunes a los que podremos recurrir para agilizar nuestras ediciones desde la herramienta ISPF.

Y eso es todo por ahora. Por tanto, quedáis invitados a la segunda parte del post, donde completaremos la revisión iniciada hoy. Una vez visto el artículo completo, ya no deberíais tener problema alguno para buscar varios ficheros a la vez desde ISPF.

Saludos.

lunes, 28 de septiembre de 2015

Subquery para recuperar varios campos a la vez

Del mismo modo que podemos obtener un campo individual, las subqueries SQL también nos sirven para recuperar varios campos a la vez de las tablas DB2. Esta operativa nos será útil en numerosas ocasiones, ya que nos permitirá ahorrarnos gran parte del código que tendríamos que emplear para extraer los datos uno a uno.

Subquery para recuperar varios campos a la vez


En general, cuando codificamos una subquery (una query anidada dentro de otra query SQL), lo que solemos hacer es crear una sentencia que nos permita acceder a un dato concreto. Este tipo de acceso habrá sido utilizado varias veces por cualquier programador Cobol que lleve más de un año utilizando el QMF de SQL.


Un ejemplo del tipo de subquery SQL DB2 sencilla al que me refiero es el que os incluyo aquí a continuación, donde la utilizamos para recuperar el campo SITUACION.

SELECT * FROM JJTRAMT0 A
WHERE A.SITUACION IN                             
     (SELECT DISTINCT SITUACION                     
      FROM JJLOCAT0                                      
      WHERE LOCALIZACION = ‘VITORIA’) 


Pues bien, en algunas ocasiones nos vamos a encontrar con problemas más complejos en el mantenimiento de nuestra aplicación y, en esos casos, nos ahorraremos bastante trabajo si implementamos una query que sea capaz de recuperar más de un campo del fichero DB2. En el ejemplo anterior, este escenario podría ser el de intentar recuperar mediante la subquery los campos SITUACION y LOCALIZACION del fichero LOCA.

Es posible que, en vuestros clientes, nunca lleguéis a encontraros en una situación en la que tengáis la necesidad de hacer una subquery tan elaborada. A pesar de todo, nunca está de más saber cómo se hace. Quizás os sea útil en el futuro.

¿Cómo recuperar varios campos a la vez del DB2?


Implementar una subquery que recupere varios campos del fichero DB2 a la vez es un procedimiento que, una vez conocido, resulta bastante sencillo de replicar. Digamos que la complejidad de este tipo de subquery tiene su origen en que no suele utilizarse asiduamente y no en que sea algo intrínsecamente complicado de desarrollar.


Para elaborar este tipo de estructura simplemente tendremos que recurrir al uso del operador || en la subquery. Dicho operador sirve, precisamente, para combinar varios campos DB2 y permitir su recuperación conjunta desde una query hija hacia su query padre. A continuación, podemos ver un ejemplo de este tipo de codificación.

SELECT * FROM JJTRAMT0 A
WHERE A.SITUACION || A.LOCALIZACION IN              
    (SELECT SITUACION || LOCALIZACION

      FROM JJLOCAT0                                      
      WHERE LOCALIZACION = ‘VITORIA’)  


Como se puede observar, en el caso anterior estamos obteniendo los campos SITUACION y LOCALIZACION en la subquery. Estos datos se combinan mediante el operador || y, posteriormente, se transfieren a la query padre en la cláusula SITUACION || LOCALIZACION.

Esta implementación nos permitirá operar en la query padre con los campos SITUACION y LOCALIZACION cuyo contenido coincida con el de los campos SITUACION y LOCALIZACION existentes en la subquery. Dicho de otro modo, la query padre recuperará los registros del fichero TRAM cuyos valores en los campos SITUACION y LOCALIZACION coincidan con alguno de los valores recuperados del fichero LOCA mediante la subquery.

Obviamente, el código anterior se puede complicar tanto como se precise, pero la idea básica de utilización del operador || es la mostrada en las sencillas declaraciones anteriores. De todas formas, si tenéis alguna duda dejad la pregunta en los comentarios e intentaré responderos en cuanto tenga oportunidad.


Conclusiones acerca del operador ||


En general, en las subqueries que construyamos nos bastará con recuperar un único campo de los ficheros DB2. Pero, tal y como hemos visto en el post, siempre que sea necesario, el operador || nos dará la oportunidad de transferir varios campos a la vez desde una subquery hasta su query padre. Aunque hasta ahora no os hayáis encontrado con dicha situación, es posible que este conocimiento os sea útil en el futuro.

Pues nada, no queda mucho más que decir acerca de este tipo especial de subquery. Espero que lo comentado os haya servido para aprender algo nuevo y útil para vuestro trabajo.

Saludos.

lunes, 21 de septiembre de 2015

ICETOOL: Como cruzar Ficheros con SPLICE (y 2)

Hace algunas semanas comenzamos a ver cómo se podía realizar un cruce de ficheros en un JCL mediante el comando SPLICE de la herramienta ICETOOL. Hoy completaremos dicha revisión, de manera que, a la conclusión del post, ya deberíamos ser capaces de crear nuestro propio Job para realizar este tipo de procesamiento.

En la primera parte del artículo empezamos a examinar cuáles eran las fichas que había que incluir en el paso 1 del JCL, esto es, en el paso necesario para reformatear los ficheros de entrada (ver post ICETOOL - Como cruzar Ficheros con SPLICE - 1). En esta segunda parte nos concentraremos en revisar las fichas correspondientes al paso 2 del JCL, en el que se procederá a generar los ficheros de salida.

PASO 2: PASO ICETOOL PARA GENERAR SALIDAS


6º) Invocación a ICETOOL: Al iniciar el paso, como siempre, se debe realizar la invocación a la herramienta ICETOOL mediante el comando EXEC PGM.

//JJ0107   EXEC PGM=ICETOOL

7º) Ficheros de entrada: En esta ficha especificamos como entrada el fichero CONCAT, que será la unión de los dos ficheros indicados en el código: SIST.JJ0105T1.DDD.X0060X.POBL.T1 y SIST.JJ0105T2.X0060X.DDD.POBL.T2. Se puede apreciar que estos dos datasets son los ficheros de salida del Paso anterior del JCL.

//* CONCAT: FICHERO UNIFICADO PARA REALIZAR EL ICETOOL        
//CONCAT   DD  DSN=SIST.JJ0105T1.DDD.X0060X.POBL.T1,
//             DISP=SHR                             

//         DD  DSN=SIST.JJ0105T2.X0060X.DDD.POBL.T2,
//             DISP=SHR  
                    

8º) Ficheros de salida: Aquí se deben indicar los nombres de los ficheros de salida de la herramienta ICETOOL, que contendrán los registros modificados por el operador. En nuestro ejemplo son el SIST.JJ0107S1.X0060X.DDD.POBL.MD (que contiene los registros del MASTER modificados según la relación del KEYS) y el SIST.JJ0107S1.X0060X.DDD.POBL.RS (que contiene los registros que no han sido modificados en la operación).

//* OUT  : FICHERO 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 : FICHERO SALIDA CON LOS REGISTROS NO MODIFICADOS
//OUT1     DD  DSN=SIST.JJ0107S2.X0060X.DDD.POBL.RS,  
//             DISP=(,CATLG,DELETE),                       
//             SPACE=(CYL,(00100,00100),RLSE),              
//             UNIT=DISCO

                                     

9º) Ficha TOOLIN: Aquí es donde tenemos que indicarle a la utilidad cuáles son las acciones que debe realizar. En nuestro caso, como estamos haciendo cruce de ficheros, tendremos que usar el operador SPLICE.

En la primera sentencia indicamos que, partiendo del fichero CONCAT, se debe transferir la información al fichero OUT realizando el cruce por el campo de longitud 6 que empieza en la posición 1 (Población). La forma de realizar dicho cruce se especificará en la ficha de control CTL3.

La cláusula WITHALL se emplea para que, en el caso de que una clave esté más de una vez en el fichero Maestro de Poblaciones (POBL.T2), se recojan todos los registros que la contengan. Si no se especifica WITHALL, entonces el filtrado se quedará únicamente con el primer registro encontrado. Por otra parte, al no incluir los comandos KEEPNODUPS y KEEPBASE, sólo saldrán en la salida los registros cuyas claves existan en ambos ficheros (POBL.T1 y POBL.T2).

Del mismo modo, en la segunda sentencia indicamos que, partiendo del fichero CONCAT, se debe transferir la información al fichero OUT1 realizando el cruce por el campo de longitud 6 que empieza en la posición 1 (Población). La forma de realizar dicho cruce se especificará en la ficha de control CTL4.


Las cláusulas KEEPNODUPS y KEEPBASE se emplean para mostrar en el fichero de salida los registros del fichero POBL.T1 cuya clave no existe en el fichero POBL.T2. Es decir, con estas cláusulas le indicamos al filtrado que nos saque toda la información de los ficheros, incluidos los registros de POBL.T1 cuyas claves no se localicen en el Maestro de Poblaciones (POBL.T2).

*--------------------------------------------------------*
* <<< 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   
    


10º) Fichas de Control: En esta tarjeta es donde tenemos que indicar cómo queremos que se realice la función SPLICE de la herramienta ICETOOL. En nuestro ejemplo, aquí estarían incluidas las fichas CTL3 y CTL4.

*--------------------------------------------------------*
* <<< 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)   



    
Esta primera ficha de control (CTL3) hace referencia al primer comando SPLICE de las sentencias del TOOLIN anterior. Como podemos ver en su codificación, en ella se hacen tres cosas con los datos de entrada.

-          OUTFIL: Se indica que la información se debe enviar desde el fichero de entrada CONCAT al fichero de salida OUT.

-          INCLUDE: Se establece la Condición de Filtrado. En esta sentencia se indica que debemos quedarnos únicamente con aquellos registros que en la posición 47 tengan un campo alfanumérico de longitud 1 igual a ‘D’ (INCLUDE=(47,1,CH,EQ,C’D’)).

-          OUTREC: A continuación, transfiere del CONCAT al OUT la siguiente información de los registros: el campo de longitud 2 que empieza en la posición 7 (7,2), el campo de longitud 6 que empieza en la posición 48 (la Población nueva) y el campo de longitud 32 que empieza en la posición 15 (15,32).

*--------------------------------------------------------*
* <<< FICHA JJRS1A08 >>>
* SACAMOS REGISTROS NO ENCONTRADOS PARA CUADRAR ENTRADA
*--------------------------------------------------------*
  OUTFIL FNAMES=OUT1,
  INCLUDE=(47,1,CH,EQ,C' '),
  OUTREC=(7,40)
 
                            


La segunda ficha de control (CTL4) hace referencia al segundo comando SPLICE de las sentencias de la TOOLIN especificada anteriormente. Al igual que en la ficha CTL3 anterior, aquí también se realizan tres acciones sobre los registros de entrada.

-          OUTFIL: Se indica que la información se debe enviar desde el fichero de entrada CONCAT al fichero de salida OUT1.

-          INCLUDE: Se establece la Condición de Filtrado. Debemos quedarnos únicamente con aquellos registros que en la posición 47 tengan un campo alfanumérico de longitud 1 igual a un espacio en blanco (INCLUDE=(47,1,CH,EQ,C’ ’)).

-          OUTREC: A continuación, transfiere del CONCAT al OUT1 el campo de longitud 40 que empieza en la posición 7 (7,40).

Una vez especificados todos los puntos anteriores, ya se podrían ejecutar sin problemas los dos pasos JCL comentados. Para personalizar estas fichas, recordad que tendríamos que cambiar tanto los nombres de los ficheros de entrada y de salida como la ubicación de los campos (de los registros) indicados en las sentencias asociadas.



Ejecución de un JCL con SPLICE


Para ver el impacto que tendría la ejecución de un operador SPLICE, podemos ver cómo irían quedando los ficheros que se generen en los dos pasos JCL anteriores. Recordemos que inicialmente partimos del fichero con la relación clave antigua – clave nueva SIST.UNLOAD.X0005X.POBL.KEYS y del fichero de poblaciones SIST.UNLOAD.X0005X.POBL.MASTER.

Tras la ejecución del primer paso, se generan dos ficheros de salida, con denominación SIST.JJ0105T1.X0060X.DDD.POBL.T1 y SIST.JJ0105T2.X0060X.DDD.POBL.T2. El fichero POBL.T1 es el fichero de relaciones entre claves (KEYS) al que, al final, se ha añadido un literal ‘D’ y el código de la clave nueva de la población.

----+----1----+----2----+----3----+----4----+----5---
***************************** Top of Data ***********
000002-100002                                 D100002
000004-100004                                 D100004
000005-100005                                 D100005
000006-100006                                 D100006
000007-100007                                 D100007
000008-100008                                 D100008
000010-100010                                 D100010
**************************** Bottom of Data *********


El fichero POBL.T2 se corresponde con el fichero maestro de poblaciones (MASTER), al que al final se le han añadido siete posiciones en blanco. Con esto se consigue que POBL.T1 y POBL.T2 tengan la misma longitud de registro.

----+----1----+----2----+----3----+----4----+----5---
***************************** Top of Data ***********
000002B-000002-ALMERIA................ALM01300    
000004B-000004-SANTANDER..............SAN01500    
000005B-000005-TARRAGONA..............TAR01600    
000006B-000006-BADAJOZ................BAD01700    
000007B-000007-SALAMANCA..............SAL01800    
000008B-000008-BURGOS.................BUR01900    
000010B-000010-SEGOVIA................SEG01100    
000011B-000011-TOLEDO.................TOL01000    
000012B-000012-GRANADA................GRA00900    
000014B-000014-CASTELLON..............CAS00700    
000015A-000015-ZARAGOZA...............ZAR00600    
000017A-000017-VALENCIA...............VAL00400    
000018A-000018-BARCELONA..............BAR00300    
000019B-000019-CIUDAD REAL............CRE00200    
000020A-000020-MADRID.................MAD00100    
**************************** Bottom of Data *********



A continuación, el segundo paso del JCL usa como entrada los dos ficheros que se acaban de generar (POBL.T1 y POBL.T2). La salida la constituyen el fichero con los registros modificados SIST.JJ0107S1.X0060X.DDD.POBL.MD y el fichero con el resto de registros que no ha sufrido ningún cambio por parte de la utilidad ICETOOL SIST.JJ0107S2.X0060X.DDD.POBL.RS.

En el dataset POBL.MD encontraremos los registros cuya clave de población antigua ha sido sustituida por la nueva (según la relación establecida en el fichero KEYS): 100002, 100004, 100005, etc…

----+----1----+----2----+----3----+----4    
***************************** Top of Data *****
B-100002-ALMERIA................ALM01300    
B-100004-SANTANDER..............SAN01500    
B-100005-TARRAGONA..............TAR01600    
B-100006-BADAJOZ................BAD01700    
B-100007-SALAMANCA..............SAL01800    
B-100008-BURGOS.................BUR01900    
B-100010-SEGOVIA................SEG01100    
**************************** Bottom of Data ***


Del mismo modo, en el fichero POBL.RS se almacenan los registros que no han sufrido ninguna modificación. Y, por tanto, continúan estando identificados por la clave de población antigua: 000011, 000012, 000014, etc…

----+----1----+----2----+----3----+----4    
***************************** Top of Data *****
B-000011-TOLEDO.................TOL01000    
B-000012-GRANADA................GRA00900    
B-000014-CASTELLON..............CAS00700    
A-000015-ZARAGOZA...............ZAR00600    
A-000017-VALENCIA...............VAL00400    
A-000018-BARCELONA..............BAR00300    
B-000019-CIUDAD REAL............CRE00200    
A-000020-MADRID.................MAD00100    
**************************** Bottom of Data ***




Finalmente, si unimos en un fichero resultante los registros de los datasets POBL.MD y POBL.RS, dispondremos del nuevo maestro de poblaciones en el que ya se han realizado los cambios de código de población requeridos.

----+----1----+----2----+----3----+----4    
***************************** Top of Data *****
B-000011-TOLEDO.................TOL01000    
B-000012-GRANADA................GRA00900    
B-000014-CASTELLON..............CAS00700    
A-000015-ZARAGOZA...............ZAR00600    
A-000017-VALENCIA...............VAL00400    
A-000018-BARCELONA..............BAR00300    
B-000019-CIUDAD REAL............CRE00200    
A-000020-MADRID.................MAD00100    
B-100002-ALMERIA................ALM01300    
B-100004-SANTANDER..............SAN01500    
B-100005-TARRAGONA..............TAR01600    
B-100006-BADAJOZ................BAD01700    
B-100007-SALAMANCA..............SAL01800    
B-100008-BURGOS.................BUR01900    
B-100010-SEGOVIA................SEG01100    
**************************** Bottom of Data ***


Como vemos, en el fichero anterior se pueden apreciar tanto códigos antiguos de población (000011-TOLEDO, 000012-GRANADA, 000014-CASTELLON, etc…) como códigos nuevos de población (100002-ALMERIA, 100004-SANTANDER, 100005-TARRAGONA, etc…). En un cliente real, a partir de ahora este sería el nuevo fichero maestro de Poblaciones. 

Conclusiones del cruce de ficheros mediante SPLICE


La verdad es que, si no la hemos realizado nunca con anterioridad, la ejecución de un cruce de ficheros mediante SPLICE nos puede parecer algo compleja. Tengo que reconocer que, al menos a mí, así me lo pareció la primera ocasión en la que tuve que enfrentarme con esta operación.


Sin embargo, os aseguro que, una vez que hayáis practicado con algunos ejemplos, os daréis cuenta de que el empleo del SPLICE del ICETOOL nos puede ahorrar muchos pasos (y mucho trabajo) a la hora de elaborar un JCL. Pensad: ¿cuánto nos habría costado implementar el ejemplo (sencillo) del artículo sin usar el SPLICE?

Siempre es complicado empezar a pelearse con una nueva utilidad Host. Pero eso no significa que lo más óptimo sea seguir trabajando con nuestros antiguos operadores de toda la vida. Aunque nos pueda parecer tedioso a corto plazo, el empleo de las utilidades más potentes nos ahorrará mucho tiempo de codificación a largo plazo. No lo olvidéis la próxima vez que os tengáis que enfrentar con un SPLICE.



En este artículo hemos tratado de ver cómo se puede realizar un cruce de ficheros mediante el operador SPLICE. Ciertamente, existen otros muchos comandos relacionados con la utilidad ICETOOL, pero este es uno de los más utilizados. De todas formas, en el Blog iremos viendo poco a poco cómo se deben implementar las operativas JCL con aquellos operadores que considero como los más importantes.

Pues nada, espero que lo comentado aquí os sirva para tener un poco más claro cuáles son los pasos a seguir a la hora de elaborar un SPLICE. Si lo he conseguido, con eso ya me puedo dar por satisfecho…

Saludos.