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]

jueves, 15 de noviembre de 2012

Recomendado: JavaScript Succinctly

Recuerdo mi primer ¡Hola mundo! con Javascript, eso fue en el año 2002, mi editor HTML en esa época era Notepad. Estoy casi seguro que todos los programaodores Web han tenido un amor a primera vista con Javascript.

Aún sin tener la plena conciencia de lo que era Javascript en esos días y de lo que llegaría hacer hoy, empecé a introducirme en el mundo mágico de este lenguaje para manipular el DOM. Navegando entre varios sitios, unos muy buenos otro no, fui mejorando mi habilidad en usar el lenguaje.

Pero a pesar de toda la experiencia adquiridad en el camino y de ser una herramienta indiscutible en mis últimos proyectos Web, nuca consideré tener un profundo conocomiento del lenguaje hasta que leí el e-book JavaScript Succinctly de Syncfusion.com. Gracias a ese libro logré entender la arquitéctura de Javascript.

miércoles, 14 de noviembre de 2012

sysindexes, sys.indexes y INFORMATION_SCHEMA

Estoy en el proceso de migrar los DTS de SQL Server 2000 a paquetes de SSIS de 2008. Estoy aprovechando para implementar algunas mejores prácticas. La primera duda que tuve fue con el uso de sysindexes para saber de la existencia de un índice, era de mi conocimiento que lo recomendado por MS es utilizar sys.indexes porque sysindexes es considerado obsoleto y se mantiene para compatibilidad con versiones anteriores, es decir que el código que escribí en 2006 aún funciona, pero aún tenía la duda ¿cuál sería la mejor práctica?

Decidí consultar con él DBA, su repuesta fue que la mejor práctica para consultar la metadata en SQL Server es utlizar el conjunto de vistas INFORMATION_SCHEMA que es un estándar ANSI que MS implentó en SQL Server, pero el estándar no contempla brindar información de los indices.

Al final mi sentencia quedó:

IF EXISTS(SELECT 1 FROM sys.indexes WHERE name = 'IDX')
 DROP INDEX nombre_tabla.IDX

Para finalizar, doy a conocer mi decepción de la función "Migrate..." para los DTS, no me ha servido para nada porque la parte fundametal que es el Data Flow no la migra.

´