miércoles, 2 de marzo de 2011

Validar Datos No Validos en Campos Numéricos en SQL

Este problema me llevo mucho esfuerzo para detectarlo y corregirlo.
Tenía un proceso Batch (CLP) que generaba un reporte, para ello, filtraba la información que necesitaba por medio de una sentencia SELECT de SQL. Ejecutaba un STRQMQRY, para generar información temporal y luego procesarla en un RPG.

El problema se presentó cuando mi proceso no generaba el reporte.
El proceso terminaba normalmente pero revisando el LOG del Job describía el siguiente mensaje:

Mensaje . . . . :   Error de conversión al asignar un valor a la columna CAMPO2. 


Causa . . . . . :   Se ha producido un error de conversión tipo 6 durante un error de conversión tipo 6 durante un intento de asignar un valor a la columna CAMPO2 con una sentencia INSERT
  

-- El tipo de error 6 son datos numéricos que no son válidos.


Según el mensaje, todo indicaba que se trataba de datos inválidos en campo numérico o empaquetado.


En la imagen, una demostración a lo que me refiero. En recuadro rojo el campo numerico con la inconsitencia.
En recuadro amarillo, el valor hexadecimal del mismo campo numerico.
Y en recuadro verde el dato con la validación, es decir, se coloca Cero en los datos que presentan datos no validos.

Los datos numéricos se pueden validar en la sentencia SELECT por medio de su valor hexadecimal. Para hacer eso, utilizamos la función HEX.
SELECT  campo1, campo2, hex(campo2),                               
     CASE                                                          
       WHEN SUBSTRING(HEX(campo2), 1, 1)||SUBSTRING(HEX(campo2), 3,
1)|| SUBSTRING(HEX(campo2), 5, 1) <> 'FFF' THEN 0                                       
       WHEN TRANSLATE(                                             
            SUBSTR(HEX(campo2),2,1)||SUBSTR(HEX(campo2),4,1)||     
            SUBSTR(HEX(campo2),6,1)||SUBSTR(HEX(campo2),8,1),      
            ' ','0123456789',' ') <> ' '  THEN 0
       WHEN SUBSTR(HEX(campo2),7,1) NOT IN ('F','D')               
                                          THEN 0                   
       ELSE campo2                                                 
     END AS campo2,                                                
        campo3, hex(campo3),                                       
     CASE                                                           
       WHEN SUBSTRING(HEX(campo3), 1, 1)||SUBSTRING(HEX(campo3), 3,
1)|| SUBSTRING(HEX(campo3), 5, 1) <> 'FFF' THEN 0 
       WHEN TRANSLATE(                                          
            SUBSTR(HEX(campo3),2,1)||SUBSTR(HEX(campo3),4,1)||  
            SUBSTR(HEX(campo3),6,1)||SUBSTR(HEX(campo3),8,1),   
            ' ','0123456789',' ') <> ' '  THEN 0                 
       WHEN SUBSTR(HEX(campo3),7,1) NOT IN ('F','D')            
                                          THEN 0                
       ELSE campo3                                              
     END AS campo3                                               
From MIUSUARIO/MIARCHIVO


Función HEX con campos numéricos:
Un campo numérico de 4 posiciones se extiende a 8 caracteres. De los cuales las posiciones impares, es decir, 1, 3, 5 y 7 deben contener ‘F’ para valores positivos.  Para valores negativos 1, 3 y 5 deben contener ‘F’.
Las posiciones pares, es decir, 2, 4, 6 y 8 deben contener un digito entre 0…9
Y por ultimo la penúltima posición debe contener D para el signo. (Solo para números negativos)

Función HEX con campos numéricos empaquetados:
Un campo empaquetado de 4 posiciones se extiende a 6 caracteres. Todas las posiciones excepto las ultima posición deben ser dígitos entre 0…9
La última posición debe contener F (número positivo) o D (número negativo).

Por ejemplo:   Campo empaquetado de 4,2 y de 4,0 respectivamente

Hacer la validación por cada campo del archivo que contenga inconsistencia resulta laborioso. Ya que nunca sabremos que campo contendrá datos inválidos. Así que cambie mi proceso, desde el RPG procesé el archivo completamente y para evitar el ERROR DE DATOS DECIMAL, lo compilé con la opción FIXNBR del compilador.


Si lo que se quiere es modificar los datos inválidos desde SQL por medio de una sentencia UPDATE, simplemente hay que agregar esas validaciones en el WHERE
Tal como lo indica en el siguiente link:



1 comentario: