miércoles, 15 de diciembre de 2010

Utilidades REXX I: Querys dinámicas.

REXX (REstructured eXtended eXecutor) es un lenguaje de programación desarrollado en IBM y, en principio, está disponible en todos los entornos mainframe. No necesita compilación y puede ejecutarse tanto desde un JCL como con un TSO EXEC.

No vamos a entrar a ver las sentencias básicas del REXX ni como construír "mi primer programa", pero si alguien tiene alguna duda, puede consultárnoslo ^^.

Lo que vamos a ver es un ejemplo de para qué podemos usar este lenguaje. En nuestro caso será para construir una query dinámica, es decir, una sentencia SELECT en la que los campos del FROM y del WHERE serán variables que tomaremos de un fichero.

¿Para qué puedo necesitar esto? Veamos el caso práctico.

Imaginemos que queremos localizar el apellido "Ercilurrutigastañaza" porque hemos cambiado los campos que contienen apellidos de nuestra base de datos y ahora ya nos cabe el apellido entero "Ercilurrutigastañazagogeascoa". Y queremos actualizarlo para que el pobre hombre tenga bien puesto su apellido en los recibos del banco.
Vamos a buscar todas las tablas donde esté almacenado ese apellido.

El problema es que los campos donde se guarda el apellido no tienen un nombre intuitivo, asi que no podemos buscar por todas las tablas el campo "APEL", por ejemplo.

Lo que buscaremos será el contenido del campo, teniendo en cuenta que el campo mide 20 posiciones y que es un carácter, buscaremos en todas las tablas los campos que midan 20 o más y que sean caracteres.

Veamos la cadena con la sentencia que nos recuperará la lista de tablas+campos en un fichero:

//*-----------------------------------------------------------
//* DESCARGA | UNLOAD | DESCARGAMOS EN UN FICHERO LA INFORMACION
//*------------------------------------------------------------
//UNLOAD EXEC PGM=IKJEFT01,DYNAMNBR=20
//SYSTSPRT DD SYSOUT=*
//SYSTSIN DD *
 DSN SYSTEM(DSNT)
 RUN PROGRAM(DSNTIAUL) PLAN(DSNTIAUL) -
 LIB('LIBRERIA.DE.TU.INSTALACION')
//SYSPRINT DD SYSOUT=*
//SYSUDUMP DD SYSOUT=*
//SYSPUNCH DD SYSOUT=*
//SYSREC00 DD DSN=XXXX.FICHERO.CAMPOS.TABLAS,
// DISP=(,CATLG,),UNIT=SYSDA,
// SPACE=(CYL,(100,50),RLSE)
//SYSIN DD *
  SELECT CHAR(TBNAME, 20)
        ,CHAR(NAME, 20)
    FROM SYSIBM.SYSCOLUMNS
   WHERE TBNAME LIKE 'TB%'
     AND COLTYPE LIKE '%CHAR%'
     AND TBCREATOR = 'DBO'
     AND LENGTH >= 20
     ;
/*


Donde:
CHAR(TBNAME, 20):Lo que mida el nombre de las tablas como máximo
CHAR(NAME, 20) :Lo que mida el nombre de los campos como máximo
SYSIBM.SYSCOLUMNS:Contiene información de cada columna de cada tabla y vista de la BD
'TB%':Parte común a todas nuestras tablas
'%CHAR%':Es el tipo de dato
'DBO':Owner DB2 que corresponda
LENGTH:Longitud del campo que buscamos

La información del fichero tendría esta pinta:
TBPRU01 CAMPO1
TBPRU01 CAMPO2
TBPRU01 CAMPO3
TBPRU02 CAMPO4
TBPRU02 CAMPO5
TBPRU02 CAMPO6
TBPRU03 CAMPO7
TBPRU03 CAMPO8
TBPRU03 CAMPO9
TBPRU04 CAMPO1
(...)

Veamos el código del programa REXX:

/* REXX */
STAT = MSG('ON')
USER=SYSVAR(SYSUID)
RXSQL_DB2SUBSYS = DSNT
"EXECIO * DISKR DESCARGA (STEM LINE. FINIS"
DO I = 1 TO LINE.0
   TABLA= STRIP(SUBSTR(LINE.I,1,20))
   CAMPO= STRIP(SUBSTR(LINE.I,21,20))
   SENTENCIA = "SELECT COUNT(*)",
               "FROM "STRIP(TABLA),
               "WHERE "STRIP(CAMPO) "= 'Ercilurrutigastañaza'"
   CALL RXSQL SENTENCIA
   IF RXSQL_SQLCODE < 0 THEN
      DO
        SAY "ERROR EN TABLA:"STRIP(TABLA) "SQLCODE:"RXSQL_SQLCODE
        SAY SENTENCIA
      END
   IF STRIP(TEMP.1.1) > 0 THEN
      DO
        SAY SENTENCIA
        SAY STRIP(TEMP.1.1)
      END
END
CALL RXSQLEND
EXIT 0

Donde:
"EXECIO * DISKR DESCARGA (STEM LINE. FINIS":Lee el fichero DESCARGA hasta el final
TABLA= STRIP(SUBSTR(LINE.I,1,20)):Los nombres de tablas del fichero
CAMPO= STRIP(SUBSTR(LINE.I,21,20)):Los nombres de campos del fichero
SAY SENTENCIA:Nos displayará las sentencias en las que encontremos el apellido que buscamos

Lo ejecutaremos en una cadena:

//*=========================================================
//* EJECUCION DEL PROGRAMA REXX
//*=========================================================
//REXTBLS EXEC PGM=IKJEFT01
//*-------
//SYSPROC DD DISP=SHR,DSN=LIBRERIA.DONDE.ESTA.EL.PROGRAMA
//DESCARGA DD DISP=SHR,DSN=XXXX.FICHERO.CAMPOS.TABLAS
//SYSTSPRT DD DSN=XXXX.LISTA.CAMPOS.APELLIDO
//         DISP=(,CATLG),
//         SPACE=(CYL,(60,10),RLSE),UNIT=SYSDA
//SYSLIST DD SYSOUT=*
//SYSOUT DD SYSOUT=*
//SYSTSIN DD *
 REXTBLS
/*

Donde:
XXXX.LISTA.CAMPOS.APELLIDO:Fichero donde escribiremos los SAY
REXTBLS:Nombre del programa REXX

Podéis descargaros el JCL completo y el código del programa.

1 comentario:

Anónimo dijo...

Voy a probarlo, desde ya gracias.
PD: Los link no funcan.