Uno no para de aprender cada día.
En un post de los foros de MSDN, en concreto el de SSIS en inglés, alguien pregunto lo siguiente:
“Estoy usando un componente RowCount para contar las filas del flujo y guardar el dato en una variable, posteriormente utilizo un Derived Column para crear una columna con el valor de la variable. La variable está siendo resetada a 0 cuando la asigno a la columna. ¿Existe algún motivo?”
Tal y como respondieron Todd C y Todd McDermid, expertos en SSIS, existen dos motivos:
1) El componente RowCount es de tipo síncrono: fila leida, fila expulsada es por esto que hasta que no pasen todas las filas no se establecerá la variable. El flujo habrá continuado y antes de que finalice el RowCount es posible que lleguen filas al Derived Column.
2) El componente Columna Derivada bloquea las variables en el evento Pre-Execute y no las desbloquea hasta el Post-Execute, por tanto las leerá con el valor anterior a la ejecución del data flow (obtenida en el control flow o en un data flow anterior).
Tuve que comprobarlo por mí mismo, que insolencia! Estaban claros los motivos, pero nunca me había topado con esta situación. Había usado RowCount y Aggregates para obtener conteos de filas, pero en ningún caso devolver el valor a todas las filas del flujo.
Creamos una variable del ámbito del flujo de datos, le ponemos el valor 99:
Diseñamos el flujo de datos añadiendo un origen con algunos datos, añadimos un componente RowCount al que asignamos la variable creada. Conectamos una columna dervidada a la salida del RowCount y creamos la columna RowCount a la que asignamos el valor de la variable. Conectamos un destino cualquiera a la salida y en el pipeline configuramos un visor de datos para revisar los valores de los campos
Pues tal como decían en el foro, el valor que contiene la variable es el establecido en el evento pre-execute del flujo de datos, que en este caso son los valores de diseño al no existir ningún componente que preceda al flujo de datos.
Para hacerle unas cosquillas al SSIS introduje un Script componente para mostrar un MessageBox el valor de la variable….
¿0? Y nuestro 99? Curioso al menos….
Me puse un poco nervioso e intenté otra aproximación para el problema. La propuesta de Todd C era romper el proceso en dos, obteniendo primero la variable en un data flow, pero sin guardarlo en destino y posteriormente hacer un update mediante un Execute SQL (en el control flow)
Pero ¿y si el destino no admite updates, como un archivo de texto o similar?
Haciendo algunas modificaciones al flujo de datos y cambiando el RowCount por un Aggregate, utilizando Sorts y un Merge Join… se puede!
Como se hizo:
1) En la columna derivada añadimos una nueva columna [JoinKey] con la expresión (DT_I1)1
2) Ordenamos el flujo por la columna [JoinKey]
3) Añadimos un Multicast
4) Una de las salidas las dirigimos a un Aggregate y lo configuramos para que cuente todas las filas agrupando por [JoinKey]. Tras el Aggregate volvemos a ordenar por [JoinKey]
5) Añadimos un Merge Join y a la entrada izquierda conectamos una la salida del multicast. A la entrada derecha conectamos la salida del Sort tras el Aggregate. Seleccionamos los datos de la izquierda y el número de filas de la izquierda.
No hay comentarios:
Publicar un comentario