Analizar formatos de archivo de texto no estándar con el componente de script

Cuando los datos de origen están organizados en un formato no estándar, puede resultar más conveniente consolidar toda la lógica de análisis en un único script que encadenar varias transformaciones de Integration Services para lograr el mismo resultado.

Ejemplo 1: analizar registros delimitados por fila

Ejemplo 2: dividir registros primarios y secundarios

[!NOTA]

Si desea crear un componente que pueda reutilizar más fácilmente en varias tareas de flujo de datos y varios paquetes, puede utilizar el código de este ejemplo de componente de script como punto de inicio para el componente de flujo de datos personalizado. Para obtener más información, vea Desarrollar un componente de flujo de datos personalizado.

Ejemplo 1: analizar registros delimitados por fila

En este ejemplo se muestra cómo tomar un archivo de texto en el que cada columna de datos aparece en una línea independiente y analizarlo en una tabla de destino utilizando el componente de script.

Para obtener más información sobre cómo configurar el componente de script para su uso como una transformación en el flujo de datos, vea Crear una transformación sincrónica con el componente de script y Crear una transformación asincrónica con el componente de script.

Para configurar este ejemplo de componente de script

  1. Cree y guarde un archivo de texto denominado rowdelimiteddata.txt que contenga los datos de origen siguientes:

    FirstName: Nancy
    LastName: Davolio
    Title: Sales Representative
    City: Seattle
    StateProvince: WA
    
    FirstName: Andrew
    LastName: Fuller
    Title: Vice President, Sales
    City: Tacoma
    StateProvince: WA
    
    FirstName: Steven
    LastName: Buchanan
    Title: Sales Manager
    City: London
    StateProvince:
    
  2. Abra Management Studio y conéctese a una instancia de SQL Server.

  3. Seleccione una base de datos de destino y abra una nueva ventana de consulta. En la ventana de consulta, ejecute el siguiente script para crear la tabla de destino:

    create table RowDelimitedData
    (
    FirstName varchar(32),
    LastName varchar(32),
    Title varchar(32),
    City varchar(32),
    StateProvince varchar(32)
    )
    
  4. Abra BI Development Studio y cree un nuevo paquete de Integration Services denominado ParseRowDelim.dtsx.

  5. Agregue un administrador de conexión de archivos planos al paquete, denomínelo RowDelimitedData y configúrelo para conectarse al archivo rowdelimiteddata.txt que creó en un paso anterior.

  6. Agregue un administrador de conexión OLE DB al paquete y configúrelo para conectarse a la instancia de SQL Server y a la base de datos donde creó la tabla de destino.

  7. Agregue una tarea de flujo de datos al paquete y haga clic en la ficha Flujo de datos del Diseñador SSIS.

  8. Agregue un origen de archivo plano al flujo de datos y configúrelo para utilizar el administrador de conexión RowDelimitedData. En la página Columnas del Editor de origen de archivos planos, seleccione la única columna externa disponible.

  9. Agregue un componente de script al flujo de datos y configúrelo como una transformación. Conecte la salida del origen de archivo plano al componente de script.

  10. Haga doble clic en el componente de script para mostrar el Editor de transformación Script.

  11. En la página Columnas de entrada del Editor de transformación Script, seleccione la única columna de entrada disponible.

  12. En la página Entradas y salidas del Editor de transformación Script, seleccione Salida 0 y establezca SynchronousInputID en 0. Cree 5 columnas de salida, todas del tipo cadena [DT_STR] con una longitud de 32:

    • FirstName

    • LastName

    • Title

    • City

    • StateProvince

  13. En la página Script del Editor de transformación Script, haga clic en Editar script y escriba el código que se muestra en la clase ScriptMain del ejemplo. Cierre el entorno de desarrollo de scripts y el Editor de transformación Script.

  14. Agregue un destino de SQL Server al flujo de datos. Configúrelo para utilizar el administrador de conexión OLE DB y la tabla RowDelimitedData. Conecte la salida del componente de script a este destino.

  15. Ejecute el paquete. Después de que el paquete haya finalizado, examine los registros en la tabla de destino de SQL Server.

    Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)

        Dim columnName As String
        Dim columnValue As String

        ' Check for an empty row.
        If Row.Column0.Trim.Length > 0 Then
            columnName = Row.Column0.Substring(0, Row.Column0.IndexOf(":"))
            ' Check for an empty value after the colon.
            If Row.Column0.Substring(Row.Column0.IndexOf(":")).TrimEnd.Length > 1 Then
                ' Extract the column value from after the colon and space.
                columnValue = Row.Column0.Substring(Row.Column0.IndexOf(":") + 2)
                Select Case columnName
                    Case "FirstName"
                        ' The FirstName value indicates a new record.
                        Me.Output0Buffer.AddRow()
                        Me.Output0Buffer.FirstName = columnValue
                    Case "LastName"
                        Me.Output0Buffer.LastName = columnValue
                    Case "Title"
                        Me.Output0Buffer.Title = columnValue
                    Case "City"
                        Me.Output0Buffer.City = columnValue
                    Case "StateProvince"
                        Me.Output0Buffer.StateProvince = columnValue
                End Select
            End If
        End If

    End Sub
public override void Input0_ProcessInputRow(Input0Buffer Row)
    {

        string columnName;
        string columnValue;

        // Check for an empty row.
        if (Row.Column0.Trim().Length > 0)
        {
            columnName = Row.Column0.Substring(0, Row.Column0.IndexOf(":"));
            // Check for an empty value after the colon.
            if (Row.Column0.Substring(Row.Column0.IndexOf(":")).TrimEnd().Length > 1)
            // Extract the column value from after the colon and space.
            {
                columnValue = Row.Column0.Substring(Row.Column0.IndexOf(":") + 2);
                switch (columnName)
                {
                    case "FirstName":
                        // The FirstName value indicates a new record.
                        this.Output0Buffer.AddRow();
                        this.Output0Buffer.FirstName = columnValue;
                        break;
                    case "LastName":
                        this.Output0Buffer.LastName = columnValue;
                        break;
                    case "Title":
                        this.Output0Buffer.Title = columnValue;
                        break;
                    case "City":
                        this.Output0Buffer.City = columnValue;
                        break;
                    case "StateProvince":
                        this.Output0Buffer.StateProvince = columnValue;
                        break;
                }
            }
        }

    }

Ejemplo 2: dividir registros primarios y secundarios

Este ejemplo muestra cómo tomar un archivo de texto, en el que una fila de separación precede a una fila de registro primario a la que siguen un número indefinido de filas de registro secundario, y cómo analizarlo en tablas de destino primarias y secundarias correctamente normalizadas mediante el componente de script. Este sencillo ejemplo se puede adaptar fácilmente a archivos de origen que utilizan más de una fila o columna para cada registro primario y secundario, siempre que exista una forma de identificar el principio y el final de cada registro.

Nota de advertenciaAdvertencia

El único fin de este ejemplo es usarlo para realizar una demostración. Si ejecuta más de una vez el ejemplo, se insertan valores de clave duplicados en la tabla de destino.

Para obtener más información sobre cómo configurar el componente de script para su uso como una transformación en el flujo de datos, vea Crear una transformación sincrónica con el componente de script y Crear una transformación asincrónica con el componente de script.

Para configurar este ejemplo de componente de script

  1. Cree y guarde un archivo de texto denominado parentchilddata.txt que contenga los datos de origen siguientes:

******** PARENT 1 DATA child 1 data child 2 data child 3 data child 4 data ******** PARENT 2 DATA child 5 data child 6 data child 7 data child 8 data ********

  1. Abra SQL Server Management Studio y conéctese a una instancia de SQL Server.

  2. Seleccione una base de datos de destino y abra una nueva ventana de consulta. En la ventana de consulta, ejecute el siguiente script para crear las tablas de destino:

    CREATE TABLE [dbo].[Parents](
    [ParentID] [int] NOT NULL,
    [ParentRecord] [varchar](32) NOT NULL,
     CONSTRAINT [PK_Parents] PRIMARY KEY CLUSTERED 
    ([ParentID] ASC)
    )
    GO
    CREATE TABLE [dbo].[Children](
    [ChildID] [int] NOT NULL,
    [ParentID] [int] NOT NULL,
    [ChildRecord] [varchar](32) NOT NULL,
     CONSTRAINT [PK_Children] PRIMARY KEY CLUSTERED 
    ([ChildID] ASC)
    )
    GO
    ALTER TABLE [dbo].[Children] ADD CONSTRAINT [FK_Children_Parents] FOREIGN KEY([ParentID])
    REFERENCES [dbo].[Parents] ([ParentID])
    
  3. Abra Business Intelligence Development Studio y cree un nuevo paquete de Integration Services denominado SplitParentChild.dtsx.

  4. Agregue un administrador de conexión de archivos planos al paquete, denomínelo ParentChildData y configúrelo para conectarse al archivo parentchilddata.txt que creó en un paso anterior.

  5. Agregue un administrador de conexión OLE DB al paquete y configúrelo para conectarse a la instancia de SQL Server y a la base de datos donde creó las tablas de destino.

  6. Agregue una tarea de flujo de datos al paquete y haga clic en la ficha Flujo de datos del Diseñador SSIS.

  7. Agregue un origen de archivo plano al flujo de datos y configúrelo para utilizar el administrador de conexión ParentChildData. En la página Columnas del Editor de origen de archivos planos, seleccione la única columna externa disponible.

  8. Agregue un componente de script al flujo de datos y configúrelo como una transformación. Conecte la salida del origen de archivo plano al componente de script.

  9. Haga doble clic en el componente de script para mostrar el Editor de transformación Script.

  10. En la página Columnas de entrada del Editor de transformación Script, seleccione la única columna de entrada disponible.

  11. En la página Entradas y salidas del Editor de transformación Script, seleccione Salida 0, cámbiele el nombre a ParentRecords y establezca SynchronousInputID en Ninguno. Cree 2 columnas de salida:

    • ParentID (la clave principal), de tipo entero de cuatro bytes con signo [DT_I4]

    • ParentRecord, de tipo cadena [DT_STR] con una longitud de 32.

  12. Cree una segunda salida y denomínela ChildRecords. El valor SynchronousInputID de la nueva salida ya está establecido en Ninguno. Cree 3 columnas de salida:

    • ChildID (la clave principal), de tipo entero de cuatro bytes con signo [DT_I4]

    • ParentID (la clave externa), también de tipo entero de cuatro bytes con signo [DT_I4]

    • ChildRecord, de tipo cadena [DT_STR] con una longitud de 50.

  13. En la página Script del Editor de transformación Script, haga clic en Editar script. En la clase ScriptMain, escriba el código mostrado en el ejemplo. Cierre el entorno de desarrollo de scripts y el Editor de transformación Script.

  14. Agregue un destino de SQL Server al flujo de datos. Conecte la salida ParentRecords del componente de script a este destino. Configúrela para utilizar el administrador de conexión OLE DB y la tabla Parents.

  15. Agregue otro destino de SQL Server al flujo de datos. Conecte la salida ChildRecords del componente de script a este destino. Configúrela para utilizar el administrador de conexión OLE DB y la tabla Children.

  16. Ejecute el paquete. Después de que el paquete haya finalizado, examine los registros primarios y secundarios en las dos tablas de destino de SQL Server.

    Public Overrides Sub Input0_ProcessInputRow(ByVal Row As Input0Buffer)

        Static nextRowIsParent As Boolean = False
        Static parentCounter As Integer = 0
        Static childCounter As Integer = 0

        ' If current row starts with separator characters,
        '  then following row contains new parent record.
        If Row.Column0.StartsWith("***") Then
            nextRowIsParent = True
        Else
            If nextRowIsParent Then
                ' Current row contains parent record.
                parentCounter += 1
                Me.ParentRecordsBuffer.AddRow()
                Me.ParentRecordsBuffer.ParentID = parentCounter
                Me.ParentRecordsBuffer.ParentRecord = Row.Column0
                nextRowIsParent = False
            Else
                ' Current row contains child record.
                childCounter += 1
                Me.ChildRecordsBuffer.AddRow()
                Me.ChildRecordsBuffer.ChildID = childCounter
                Me.ChildRecordsBuffer.ParentID = parentCounter
                Me.ChildRecordsBuffer.ChildRecord = Row.Column0
            End If
        End If

    End Sub
public override void Input0_ProcessInputRow(Input0Buffer Row)
    {

    int static_Input0_ProcessInputRow_childCounter = 0;
    int static_Input0_ProcessInputRow_parentCounter = 0;
    bool static_Input0_ProcessInputRow_nextRowIsParent = false;

        // If current row starts with separator characters, 
        // then following row contains new parent record. 
        if (Row.Column0.StartsWith("***"))
        {
            static_Input0_ProcessInputRow_nextRowIsParent = true;
        }
        else
        {
            if (static_Input0_ProcessInputRow_nextRowIsParent)
            {
                // Current row contains parent record. 
                static_Input0_ProcessInputRow_parentCounter += 1;
                this.ParentRecordsBuffer.AddRow();
                this.ParentRecordsBuffer.ParentID = static_Input0_ProcessInputRow_parentCounter;
                this.ParentRecordsBuffer.ParentRecord = Row.Column0;
                static_Input0_ProcessInputRow_nextRowIsParent = false;
            }
            else
            {
                // Current row contains child record. 
                static_Input0_ProcessInputRow_childCounter += 1;
                this.ChildRecordsBuffer.AddRow();
                this.ChildRecordsBuffer.ChildID = static_Input0_ProcessInputRow_childCounter;
                this.ChildRecordsBuffer.ParentID = static_Input0_ProcessInputRow_parentCounter;
                this.ChildRecordsBuffer.ChildRecord = Row.Column0;
            }
        }

    }
Icono de Integration Services (pequeño) Manténgase al día con Integration Services

Para obtener las más recientes descargas, artículos, ejemplos y vídeos de Microsoft, así como soluciones seleccionadas de la comunidad, visite la página de Integration Services en MSDN o TechNet:

Para recibir notificaciones automáticas de estas actualizaciones, suscríbase a las fuentes RSS disponibles en la página.