sql >> Base de Datos >  >> RDS >> Sqlserver

¿Por qué SSIS no reconoce el delimitador de fila de avance de línea {LF} al importar un archivo plano UTF-8?

Causa:

SSIS no puede leer el archivo y muestra la siguiente advertencia debido al delimitador de columna Ç ("c" con cedilla ) y not debido al delimitador de línea {LF} (Salto de línea ).

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.

Aquí hay un paquete de SSIS de muestra que muestra cómo resolver el problema usando Script Component y al final hay otro ejemplo que simula su problema.

Resolución:

El siguiente paquete de muestra está escrito en SSIS 2008 R2 . Lee un archivo plano con delimitador de fila {LF} como valor de una sola columna; luego divide los datos usando Script Component para insertar la información en una tabla en SQL Server 2008 R2 base de datos.

Utilice Notepad++ para crear un archivo plano simple con pocas filas. El siguiente archivo de muestra tiene Id. de producto y Precio de lista información en cada fila separada por Ç como delimitador de columna y cada fila termina con {LF} delimitador.

En Notepad++, haga clic en Encoding y luego haga clic en Encoding in UTF-8 para guardar el archivo plano en UTF-8 codificación.

La muestra usará un SQL Server 2008 R2 base de datos llamada Sora . Cree una nueva tabla llamada dbo.ProductListPrice usando el script dado a continuación. SSIS insertará los datos del archivo sin formato en esta tabla.

USE Sora;
GO

CREATE TABLE dbo.ProductListPrice
(
        ProductId   nvarchar(30)    NOT NULL
    ,   ListPrice   numeric(12,2)   NOT NULL
);
GO

Cree un paquete SSIS con Business Intelligence Development Studio (BIDS) 2008 R2 . Nombre el paquete como SO_6268205.dtsx . Cree una fuente de datos llamada Sora.ds para conectarse a la base de datos Sora en SQL Server 2008 R2 .

Haga clic derecho en cualquier lugar dentro del paquete y luego haga clic en Variables para ver el panel de variables. Cree una nueva variable llamada ColumnDelimiter de tipo de datos String en el alcance del paquete SO_6268205 y establezca la variable con el valor Ç

Haga clic con el botón derecho en Connection Managers y haga clic en New Flat File Connection... para crear una conexión para leer el archivo plano.

En el General página del Editor del administrador de conexiones de archivos planos , realice las siguientes acciones:

  • Establecer Nombre del administrador de conexiones a ProductListPrice
  • Establecer Descripción a Flat file connection manager to read product list price information.
  • Seleccione la ruta del archivo sin formato. Tengo el archivo en la ruta C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt
  • Seleccione {LF} from Delimitador de fila de encabezado
  • Verifique Column names in the first data row
  • Haga clic en Columns página

En las Columns página del Editor del administrador de conexiones de archivos planos , verifique que el Column delimiter está en blanco y deshabilitado. Haga clic en Advanced página.

En el Advanced página del Editor del administrador de conexiones de archivos planos , realice las siguientes acciones.

  • Establecer el Nombre a LineData
  • Verifique que el Delimitador de columna se establece en {LF}
  • Establecer el Tipo de datos a Unicode string [DT_WSTR]
  • Establezca el Ancho de la columna de salida a 255
  • Haga clic en Preview página.

En la Preview página del Editor del administrador de conexiones de archivos planos , verifique que los datos mostrados sean correctos y haga clic en OK .

Verá la fuente de datos Sora y el administrador de conexión de archivos planos ProductListPrice en los Connection Managers pestaña en la parte inferior del paquete.

Arrastre y suelte Data Flow Task en el Flujo de control pestaña del paquete y asígnele el nombre File to database - Without Cedilla delimiter

Haga doble clic en Tarea de flujo de datos para cambiar la vista al Data Flow pestaña en el paquete. Arrastre y suelte un Flat File Source en el Flujo de datos pestaña. Haga doble clic en Fuente de archivo plano para abrir Flat File Source Editor .

En el Connection Manager página del Editor de fuente de archivo plano , seleccione el Administrador de conexión de archivos planos ProductListPrice y haga clic en Columnas página.

En las Columns página del Editor de fuente de archivo plano , marque la columna LineData y haz clic en OK .

Arrastre y suelte un Script Component en el Flujo de datos pestaña debajo de Fuente de archivo plano , seleccione Transformation y haz clic en OK . Conecte la flecha verde de Fuente de archivo plano a Componente de secuencia de comandos . Haga doble clic en Componente de secuencia de comandos para abrir Script Transformation Editor .

Haga clic en Columnas de entrada en Editor de transformación de secuencias de comandos y seleccione LineData columna. Haga clic en Entradas y salidas página.

En las Inputs and Outputs página del Editor de transformación de secuencias de comandos , realice las siguientes acciones.

  • Cambiar el nombre de las entradas a FlatFileInput
  • Cambie el nombre de las salidas a SplitDataOutput
  • Seleccione Columnas de salida y haga clic en Add Column . Repita esto nuevamente para agregar otra columna.
  • Nombre la primera columna ProductId
  • Establecer el Tipo de datos de la columna ProductId a Unicode string [DT_WSTR]
  • Establecer la longitud a 30

En las Inputs and Outputs página del Editor de transformación de secuencias de comandos , realice las siguientes acciones.

  • Nombre la segunda columna ListPrice
  • Establecer el Tipo de datos de la columna PrecioDeLista a numeric [DT_NUMERIC]
  • Establecer la Precisión a 12
  • Establecer la Escala a 2
  • Haga clic en Secuencia de comandos página para modificar el script

En el Script página del Editor de transformación de secuencias de comandos , realice las siguientes acciones.

  • Haga clic en el botón de puntos suspensivos junto a ReadOnlyVariables y seleccione la variable User::ColumnDelimiter
  • Haga clic en Edit Script...

Pegue el siguiente C# en el Editor de secuencias de comandos. El script realiza las siguientes tareas.

  • Uso del valor del delimitador de columna Ç definido en la variable Usuario::ColumnDelimiter , el método FlatFileInput_ProcessInputRow divide el valor entrante y lo asigna a las dos columnas de salida definidas en la transformación del componente de secuencia de comandos.

Código de componente de script en C#

using System;
using System.Data;
using Microsoft.SqlServer.Dts.Pipeline.Wrapper;
using Microsoft.SqlServer.Dts.Runtime.Wrapper;

[Microsoft.SqlServer.Dts.Pipeline.SSISScriptComponentEntryPointAttribute]
public class ScriptMain : UserComponent
{
    public override void PreExecute()
    {
        base.PreExecute();
    }

    public override void PostExecute()
    {
        base.PostExecute();
    }

    public override void FlatFileInput_ProcessInputRow(FlatFileInputBuffer Row)
    {
        const int COL_PRODUCT = 0;
        const int COL_PRICE = 1;

        char delimiter = Convert.ToChar(this.Variables.ColumnDelimiter);
        string[] lineData = Row.LineData.ToString().Split(delimiter);

        Row.ProductId = String.IsNullOrEmpty(lineData[COL_PRODUCT]) 
                            ? String.Empty 
                            : lineData[COL_PRODUCT];

        Row.ListPrice = String.IsNullOrEmpty(lineData[COL_PRICE]) 
                            ? 0 
                            : Convert.ToDecimal(lineData[COL_PRICE]);
    }
}

Arrastre y suelte OLE DB Destination en el Flujo de datos pestaña. Conecte la flecha verde de Componente de secuencia de comandos a Destino OLE DB . Haga doble clic en Destino OLE DB para abrir OLE DB Destination Editor .

En el Connection Manager página del Editor de destino OLE DB , realice las siguientes acciones.

  • Seleccione Sora desde Administrador de conexión OLE DB
  • Seleccione Table or view - fast load desde Modo de acceso a datos
  • Seleccione [dbo].[ProductListPrice] from Nombre de la tabla o la vista
  • Haga clic en Asignaciones página

Haga clic en Mappings página en el Editor de destino OLE DB asignaría automáticamente las columnas si los nombres de las columnas de entrada y salida son los mismos. Haz clic en OK .

Flujo de datos La pestaña debería verse así después de configurar todos los componentes.

Ejecute la consulta select * from dbo.ProductListPrice en SQL Server Management Studio (SSMS) para encontrar el número de filas en la tabla. Debe estar vacío antes de ejecutar el paquete.

Ejecutar el paquete. Notará que el paquete procesó con éxito 9 filas El archivo plano contiene 10 líneas pero la primera fila es el encabezado con los nombres de las columnas.

Ejecute la consulta select * from dbo.ProductListPrice en SQL Server Management Studio (SSMS) para encontrar el 9 filas insertadas con éxito en la tabla. Los datos deben coincidir con los datos del archivo plano.

El ejemplo anterior ilustró cómo dividir manualmente los datos usando Script Component porque el Administrador de conexión de archivos planos encuentra un error al configurar el delimitador de columna Ç

Simulación de problemas:

Este ejemplo muestra un Administrador de conexión de archivos planos separado configurado con delimitador de columna Ç , que se ejecuta pero encuentra una advertencia y no procesa ninguna línea.

Haga clic con el botón derecho en Connection Managers y haga clic en New Flat File Connection... para crear una conexión para leer el archivo plano. En el General página del Editor del administrador de conexiones de archivos planos , realice las siguientes acciones:

  • Establecer Nombre del administrador de conexiones a ProductListPrice_Cedilla
  • Establezca Descripción en Flat file connection manager with Cedilla column delimiter.
  • Tengo el archivo en la ruta C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt Seleccione la ruta del archivo sin formato.
  • Seleccione {LF} from Delimitador de fila de encabezado
  • Verifique Column names in the first data row
  • Haga clic en Columns página

En las Columns página del Editor del administrador de conexiones de archivos planos , realice las siguientes acciones:

  • Establecer delimitador de fila a {LF}
  • El campo delimitador de columna puede estar deshabilitado. Haga clic en Reset Columns
  • Establecer delimitador de columna a Ç
  • Haga clic en Advanced página

En el Advanced página del Editor del administrador de conexiones de archivos planos , realice las siguientes acciones:

  • Establecer el Nombre a ProductId
  • Establezca el ColumnDelimiter a Ç
  • Establecer el Tipo de datos a Unicode string [DT_WSTR]
  • Establecer la longitud a 30
  • Haga clic en la columna ListPrice

En el Advanced página del Editor del administrador de conexiones de archivos planos , realice las siguientes acciones:

  • Establecer el Nombre a ListPrice
  • Establezca el ColumnDelimiter a {LF}
  • Establecer el Tipo de datos a numeric [DT_NUMERIC]
  • Establecer la Precisión de datos a 12
  • Establecer la escala de datos a 2
  • Haga clic en OK

Arrastre y suelte una Data Flow task en el Flujo de control pestaña y asígnele el nombre File to database - With Cedilla delimiter . Deshabilite la primera tarea de flujo de datos.

Configure la segunda tarea de flujo de datos con Flat File Source y OLE DB Destination

Haga doble clic en Fuente de archivo plano para abrir Flat File Source Editor . En el Connection Manager página del Editor de fuente de archivo plano , seleccione el Administrador de conexión de archivos planos ProductListPrice_Cedilla y haga clic en Columnas página para configurar las columnas. Haz clic en OK .

Ejecutar el paquete. Todos los componentes se mostrarán en color verde para indicar que el proceso fue exitoso, pero no se procesarán filas. Puede ver que no hay indicación de números de fila entre el Flat File Source y OLE DB Destination

Haga clic en Progress pestaña y notará el siguiente mensaje de advertencia.

[Read flat file [1]] Warning: The end of the data file was reached while 
reading header rows. Make sure the header row delimiter and the number of 
header rows to skip are correct.