viernes, 16 de noviembre de 2012

SSIS: NULL(DT_STR, «length», «code_page»)

Migrando un DTS de SQL Server 2000 a un paquete de SSIS 2008, me econtré dos situaciones muy interesante.

Escenario


El DTS se encarga de cargar un archivo de texto plano de una fuente externa a una tabla en SQL Server, en una columna tipo fecha se presenta una particularidad. El campo presenta tres valores diferentes:

  1. vacío, separador de columna continuo (,,) el cual se intepreta como valor nulo
  2. el texto NULL
  3. o una fecha con hora (01/01/2012 00:00:00)

DTS Preview
Imagen 1 - Columna con tres diferentes valores

Caso 1


Con el DTS de SQL Server 2000 los datos se cargan sin ninguna complicación, tanto vacío como NULL son intepretado como un valor nulo en la tabla. Esto no ocurre en el paquete SSIS 2008, sino que se genera un error "The value could not be converted because of a potential loss of data.", el motivo de este error es obvio, el texto NULL no se puede convertir a una fecha validad.

Datos en la Tabla
Imagen 2 - Datos importados a SQL Server


La solución a este caso fue utilizar una transformación Derived Column, esta me permite evaluar el valor de la columna problemática y generar uno nuevo a partir de este.


Caso 2

Como el problema era el valor NULL, por lo anto el objetivo consistió en usar la transformación Derived Column para remplazarlo por vacío, además se configuró la transformación para que sobreescriba el campo y no generar una columna nueva. El tipo de dato de la columna era string[DT_STR] esto es de esperarse porque la fuente de los datos es un archivo de texto plano.

En la primera expresión que escribí utilicé la función NULL(DT_STR, «length», «code_page»), esta función debería de devolver un valor vacío (nulo) válido para el tipo de dato de la columna origen.

[Column 53] == "NULL" ? NULL(DT_STR,50,1252) : [Column 53]


Pero la expresión generaba este error:

Error at Cargo datos [Derived Column [369]]: For operands of the conditional operator, the data type DT_STR is supported only for input columns and cast operations. The expression "[Column 53] == "NULL" ? NULL(DT_STR,50,1252) : [Column 53]" has a DT_STR operand that is not an input column or the result of a cast, and cannot be used with the conditional operation. To perform this operation, the operand needs to be explicitly cast with a cast operator.
¿Qué? El mensaje de error explica que el valor resultante debe provenir de una columna de entrada o o de una operación de conversión de tipos. Entonces, el tercer argumento del operador ternario ?: esta correcto porque el valor proviene de una columna de entrada de datos, pero el segúndo argumento es la función NULL() que no es un cast ni es un una columna de entrada, por lo tanto lo correcto es:

--ahora con cast
[Column 53]=="NULL"?(DT_STR,50,1252)NULL(DT_STR,50,1252):[Column 53]


Resumen

--incorrecto
[Column 53]=="NULL"?NULL(DT_STR,50,1252):[Column 53]
--cast incorreto
(DT_STR,50,1252)([Column 53]=="NULL"?NULL(DT_STR,50,1252):[Column 53])
--correcto
[Column 53]=="NULL"?(DT_STR,50,1252)NULL(DT_STR,50,1252):[Column 53]
´