Desarrollando en Cobol y Natural sobre Plataforma Mainframe

miércoles, 16 de julio de 2014

Error al definir una Variable Host entre OPEN y FETCH

Se trata de un problema típico que suele aparecer cuando los programadores novatos intentan hacer sus primeros programas Cobol con tratamiento de tablas DB2. Normalmente es debido a que aún continúan pensando que trabajan con su lenguaje de programación anterior, en el que no se precisaba ningún tratamiento de cursores asociados a las tablas de la base de datos.

Cuando se une lo anteriormente comentado con el empleo de variables Fecha, es muy común que en la ejecución del programa aparezca el SQLCODE -180. Entonces el programador se vuelve loco tratando de identificar qué es lo que ha definido mal a la hora de invocar al SQL.

El error SQLCODE -180 está asociado al siguiente mensaje: "THE DATE, TIME OR TIMESTAMP VALUE value IS INVALID". Significa que estamos intentando hacer un acceso a un campo de tipo Hora o Fecha de la tabla DB2 con un dato con formato incorrecto.



Aquí tenemos un ejemplo de código que daría el error SQLCODE -180 mencionado.

 DATA DIVISON.
 WORKING-STORAGE SECTION.
***********************************************
* INTERFAZ DB2                                
***********************************************

         EXEC SQL         
           INCLUDE FACTURAS
         END-EXEC. 

*        
         EXEC SQL DECLARE FACTURAS-C CURSOR FOR
           SELECT *                           
           FROM   FACTURAS                    
           WHERE  FINACTIV < :WFIN         
           ORDER BY NUMERNIF                  
         END-EXEC.                              

.
.
.
 PROCEDURE DIVISION.
*                              
*    ABRIMOS FICHEROS Y CURSORES
*    ---------------------------
         EXEC SQL              
           OPEN FACTURAS-C     
         END-EXEC.      

.
.
.    
     MOVE FECHA-ACTIV-F   TO WFIN
                     
*                                                  
*    LEEMOS REGISTRO DEL FICHERO DE DATOS (FACTURAS)
*    --------------------------------------        
         EXEC SQL                                  
           FETCH FACTURAS-C                        
             INTO                                  
                  :NUMERNIF,                       
                  :FINACTIV,

                  :CSITCUEN       
         END-EXEC                   

        
Como podemos observar, el código anterior se divide en 3 partes.

1º) En la primera se define el cursor FACTURAS-C de la tabla DB2 FACTURAS, que precisará recibir como parámetro de entrada la variable WFIN (fecha de actividad).

2º) En la segunda se realiza la apertura del cursor FACTURAS-C mediante el comando OPEN.

3º) En la tercera se carga el valor de la variable WFIN, y se realiza una invocación al cursor FACTURAS-C mediante el comando FETCH. Esta acción recuperará información de la tabla FACTURAS en función de la fecha provisionada en el parámetro WFIN.

Pues bien, al ejecutar el código anterior nuestro programa nos devolverá un error SQLCODE -180 al intentar hacer el OPEN del cursor FACTURAS-C. Aunque este error hace referencia a que la fecha FINACTIV especificada tiene un formato incorrecto, curiosamente el problema no tiene nada que ver con la fecha que hemos provisionado en la variable WFIN.



En realidad, el error se produce debido a que hemos especificado el valor del parámetro WFIN entre el OPEN del cursor y la sentencia FETCH. Por tanto, cuando el SQL va a realizar el OPEN de FACTURAS-C se encuentra con que el parámetro host WFIN aún no tiene ninguna fecha provisionada y devuelve un SQLCODE -180, queriendo indicar con ello que no tiene formato fecha.

Por tanto, lo correcto en estos casos es indicar el valor de las variables host empleadas en el cursor antes de realizar el OPEN del mismo. La sentencia FETCH lo único que hace es recuperar el siguiente registro del DB2 en función de la extracción propuesta en la apertura del cursor, así que no tiene sentido que definamos las variables después de hacer la invocación al OPEN..

Haciendo dicho cambio, la PROCEDURE DIVISION del ejemplo anterior quedaría del siguiente modo:

 PROCEDURE DIVISION.
     MOVE FECHA-ACTIV-F   TO WFIN     
*                              
*    ABRIMOS FICHEROS Y CURSORES
*    ---------------------------
         EXEC SQL              
           OPEN FACTURAS-C     
         END-EXEC.      

.
.
.                       
*                                                  
*    LEEMOS REGISTRO DEL FICHERO DE DATOS (FACTURAS)
*    --------------------------------------        
         EXEC SQL                                  
           FETCH FACTURAS-C                        
             INTO                                  
                  :NUMERNIF,                       
                  :FINACTIV,

                  :CSITCUEN       
         END-EXEC 


Obviamente, no se trata de un error que se observe entre los programadores experimentados pero, sin embargo, hemos visto a muchos principiantes cometerlo. Normalmente, se trata de personas que previamente han trabajado con otros lenguajes en los que no era necesario hacer un OPEN previo a la lectura del fichero de base de datos. Por tanto, caen en el error de provisionar los parámetros del cursor justo antes del FETCH, creyendo que este último comando va a funcionar del mismo modo que el READ de otros lenguajes. Pero bueno, una vez que se encuentran con este problema, aprenden rápidamente la lección y la cosa no vuelve a repetirse.

La "ventaja" de este error es que, al estar trabajando con OPEN y FETCH, no vamos a producir ningún daño irreparable con la ejecución de nuestro programa. Lo único que tendremos que hacer es corregir el código y volver a compilar y linkeditar el objeto.

Si a vosotros os pasa esto mismo alguna vez, al menos esperamos que este post os sirva de ayuda para solucionar el problema con rapidez y perder el menor tiempo posible. Con eso nos damos por satisfechos.

Saludos.

No hay comentarios:

Publicar un comentario

Related Posts Plugin for WordPress, Blogger...