Sqlserver
 sql >> Datenbank >  >> RDS >> Sqlserver

Warum erkennt SSIS beim Importieren von UTF-8-Flatfiles das Zeilentrennzeichen {LF} für Zeilenvorschübe nicht?

Ursache:

SSIS kann die Datei nicht lesen und zeigt die folgende Warnung aufgrund des Spaltentrennzeichens Ç an ("c" mit Cedille ) und not aufgrund des Zeilentrennzeichens {LF} (Zeilenvorschub ).

[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.

Hier ist ein SSIS-Beispielpaket, das zeigt, wie das Problem mit Script Component behoben werden kann und am Ende gibt es ein weiteres Beispiel, das Ihr Problem simuliert.

Lösung:

Das folgende Beispielpaket ist in SSIS 2008 R2 geschrieben . Es liest eine flache Datei mit dem Zeilentrennzeichen {LF} als einzelner Spaltenwert; teilt dann die Daten mit Script Component auf um die Informationen in eine Tabelle in SQL Server 2008 R2 einzufügen Datenbank.

Verwenden Sie Notepad++ um eine einfache flache Datei mit wenigen Zeilen zu erstellen. Die folgende Beispieldatei hat Produkt-ID und Listenpreis Informationen zu jeder Zeile, getrennt durch Ç als Spaltentrennzeichen und jede Zeile endet mit {LF} Trennzeichen.

Klicken Sie in Notepad++ auf Encoding und klicken Sie dann auf Encoding in UTF-8 um die Flatfile in UTF-8 zu speichern Codierung.

Das Beispiel verwendet einen SQL Server 2008 R2 Datenbank namens Sora . Erstellen Sie eine neue Tabelle namens dbo.ProductListPrice mit dem unten angegebenen Skript. SSIS fügt die Flatfile-Daten in diese Tabelle ein.

USE Sora;
GO

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

Erstellen Sie ein SSIS-Paket mit Business Intelligence Development Studio (BIDS) 2008 R2 . Benennen Sie das Paket als SO_6268205.dtsx . Erstellen Sie eine Datenquelle namens Sora.ds um sich mit der Datenbank Sora zu verbinden in SQL Server 2008 R2 .

Klicken Sie mit der rechten Maustaste auf eine beliebige Stelle im Paket und klicken Sie dann auf Variables , um den Variablenbereich anzuzeigen. Erstellen Sie eine neue Variable namens ColumnDelimiter vom Datentyp String im Paketbereich SO_6268205 und setzen Sie die Variable mit dem Wert Ç

Klicken Sie mit der rechten Maustaste auf Connection Managers und klicken Sie auf New Flat File Connection... zum Erstellen einer Verbindung zum Lesen der Flatfile.

Auf General Seite des Flat File Connection Manager Editor , führen Sie die folgenden Aktionen aus:

  • Legen Sie den Namen des Verbindungsmanagers fest zu ProductListPrice
  • Legen Sie Beschreibung fest zum Flat file connection manager to read product list price information.
  • Wählen Sie den Flatfile-Pfad aus. Ich habe die Datei im Pfad C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt
  • Wählen Sie {LF} vom Kopfzeilentrennzeichen
  • Überprüfen Sie Column names in the first data row
  • Klicken Sie auf Columns Seite

Auf den Columns Seite des Flat File Connection Manager Editor , überprüfen Sie, ob das Column delimiter ist leer und deaktiviert. Klicken Sie auf Advanced Seite.

Auf Advanced Seite des Flat File Connection Manager Editor , führen Sie die folgenden Aktionen aus.

  • Legen Sie den Namen fest zu LineData
  • Vergewissern Sie sich, dass das Spaltentrennzeichen auf {LF} eingestellt ist
  • Legen Sie den Datentyp fest zu Unicode string [DT_WSTR]
  • Legen Sie die OutputColumnWidth fest bis 255
  • Klicken Sie auf Preview Seite.

Auf der Preview Seite des Flat File Connection Manager Editor , vergewissern Sie sich, dass die angezeigten Daten korrekt aussehen, und klicken Sie auf OK .

Sie sehen die Datenquelle Sora und der Flatfile-Verbindungsmanager ProductListPrice auf den Connection Managers Registerkarte am unteren Rand des Pakets.

Ziehen Sie Data Flow Task per Drag-and-Drop auf den Kontrollfluss des Pakets und benennen Sie es als File to database - Without Cedilla delimiter

Doppelklicken Sie auf die Datenflussaufgabe um die Ansicht auf den Data Flow umzuschalten Registerkarte auf dem Paket. Ziehen Sie eine Flat File Source und legen Sie sie dort ab auf dem Datenfluss Tab. Doppelklicken Sie auf die Flatfile-Quelle um den Flat File Source Editor zu öffnen .

Auf dem Connection Managers Seite des Flat File Source Editor , wählen Sie den Verbindungsmanager für Flatfiles aus ProductListPrice und klicken Sie auf Spalten Seite.

Auf den Columns Seite des Flat File Source Editor , prüfen Sie die Spalte LineData und klicken Sie auf OK .

Ziehen Sie eine Script Component und legen Sie sie dort ab auf den Datenfluss unter der Flatfile-Quelle , wählen Sie Transformation und klicken Sie auf OK . Verbinden Sie den grünen Pfeil von Flat File Source zu Skriptkomponente . Doppelklicken Sie auf Skriptkomponente um den Script Transformation Editor zu öffnen .

Klicken Sie auf Eingabespalten im Skript-Transformations-Editor und wählen Sie LineData Säule. Klicken Sie auf Eingänge und Ausgänge Seite.

Auf den Inputs and Outputs Seite des Skript-Transformations-Editors , führen Sie die folgenden Aktionen aus.

  • Ändern Sie den Eingabenamen in FlatFileInput
  • Ändern Sie den Ausgabenamen in SplitDataOutput
  • Wählen Sie Ausgabespalten und klicken Sie auf Add Column . Wiederholen Sie dies erneut, um eine weitere Spalte hinzuzufügen.
  • Benennen Sie die erste Spalte ProductId
  • Legen Sie den Datentyp fest der Spalte ProductId zu Unicode string [DT_WSTR]
  • Stellen Sie die Länge ein bis 30

Auf den Inputs and Outputs Seite des Skript-Transformations-Editors , führen Sie die folgenden Aktionen aus.

  • Benennen Sie die zweite Spalte ListPrice
  • Legen Sie den Datentyp fest der Spalte ListPrice zu numeric [DT_NUMERIC]
  • Legen Sie die Präzision fest bis 12
  • Stellen Sie den Maßstab ein zu 2
  • Klicken Sie auf Skript Seite, um das Skript zu ändern

Auf dem Script Seite des Skript-Transformations-Editors , führen Sie die folgenden Aktionen aus.

  • Klicken Sie auf die Schaltfläche mit den Auslassungspunkten neben ReadOnlyVariables und wählen Sie die Variable User::ColumnDelimiter aus
  • Klicken Sie auf Edit Script...

Fügen Sie das folgende C# in den Skript-Editor ein. Das Skript führt die folgenden Aufgaben aus.

  • Verwenden des Spaltentrennzeichenwerts Ç definiert in der Variable User::ColumnDelimiter , die Methode FlatFileInput_ProcessInputRow teilt den eingehenden Wert auf und weist ihn den beiden Ausgabespalten zu, die in der Skriptkomponenten-Umwandlung definiert sind.

Skriptkomponentencode in 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]);
    }
}

Ziehen Sie OLE DB Destination per Drag &Drop auf den Datenfluss Tab. Verbinden Sie den grünen Pfeil von Skriptkomponente an OLE DB-Ziel . Doppelklicken Sie auf OLE DB-Ziel um den OLE DB Destination Editor zu öffnen .

Auf dem Connection Managers Seite des OLE DB Destination Editor , führen Sie die folgenden Aktionen aus.

  • Wählen Sie Sora aus OLE DB Connection Manager
  • Wählen Sie Table or view - fast load aus dem Datenzugriffsmodus
  • Wählen Sie [dbo].[ProductListPrice] aus from Name der Tabelle oder der Ansicht
  • Klicken Sie auf Zuordnungen Seite

Klicken Sie auf Mappings Seite im OLE DB-Ziel-Editor würde die Spalten automatisch zuordnen, wenn die Eingabe- und Ausgabespaltennamen identisch sind. Klicken Sie auf OK .

Datenfluss Registerkarte sollte nach der Konfiguration aller Komponenten in etwa so aussehen.

Führen Sie die Abfrage select * from dbo.ProductListPrice aus im SQL Server Management Studio (SSMS) um die Anzahl der Zeilen in der Tabelle zu finden. Es sollte leer sein, bevor das Paket ausgeführt wird.

Führen Sie das Paket aus. Sie werden feststellen, dass das Paket 9 erfolgreich verarbeitet hat Reihen. Die Flatfile enthält 10 Zeilen, aber die erste Zeile ist eine Kopfzeile mit Spaltennamen.

Führen Sie die Abfrage select * from dbo.ProductListPrice aus im SQL Server Management Studio (SSMS) um die 9 zu finden Zeilen erfolgreich in die Tabelle eingefügt. Die Daten sollten mit Flatfile-Daten übereinstimmen.

Das obige Beispiel veranschaulicht, wie die Daten mit der Skriptkomponente manuell aufgeteilt werden weil der Flat File Connection Manager tritt bei der Konfiguration des Spaltentrennzeichens Ç auf Fehler

Ausgabesimulation:

Dieses Beispiel zeigt einen separaten Flat File Connection Manager konfiguriert mit Spaltentrennzeichen Ç , die ausgeführt wird, aber auf eine Warnung stößt und keine Zeilen verarbeitet.

Klicken Sie mit der rechten Maustaste auf Connection Managers und klicken Sie auf New Flat File Connection... um eine Verbindung zum Lesen der Flatfile herzustellen. Auf General Seite des Flat File Connection Manager Editor , führen Sie die folgenden Aktionen aus:

  • Legen Sie den Namen des Verbindungsmanagers fest zu ProductListPrice_Cedilla
  • Setzen Sie Beschreibung auf Flat file connection manager with Cedilla column delimiter.
  • Ich habe die Datei im Pfad C:\Siva\StackOverflow\Files\6268205\ProductListPrice.txt Wählen Sie den Flatfile-Pfad aus.
  • Wählen Sie {LF} vom Kopfzeilentrennzeichen
  • Überprüfen Sie Column names in the first data row
  • Klicken Sie auf Columns Seite

Auf den Columns Seite des Flat File Connection Manager Editor , führen Sie die folgenden Aktionen aus:

  • Legen Sie Zeilentrennzeichen fest zu {LF}
  • Das Spaltenbegrenzungsfeld ist möglicherweise deaktiviert. Klicken Sie auf Reset Columns
  • Setzen Sie Spaltentrennzeichen zu Ç
  • Klicken Sie auf Advanced Seite

Auf Advanced Seite des Flat File Connection Manager Editor , führen Sie die folgenden Aktionen aus:

  • Legen Sie den Namen fest zu ProductId
  • Legen Sie das ColumnDelimiter fest zu Ç
  • Legen Sie den Datentyp fest zu Unicode string [DT_WSTR]
  • Stellen Sie die Länge ein bis 30
  • Klicken Sie auf die Spalte ListPrice

Auf Advanced Seite des Flat File Connection Manager Editor , führen Sie die folgenden Aktionen aus:

  • Legen Sie den Namen fest zu ListPrice
  • Legen Sie das ColumnDelimiter fest zu {LF}
  • Legen Sie den Datentyp fest zu numeric [DT_NUMERIC]
  • Legen Sie die Datenpräzision fest bis 12
  • Stellen Sie die Datenskalierung ein zu 2
  • Klicken Sie auf OK

Ziehen Sie eine Data Flow Task per Drag-and-Drop auf den Kontrollfluss und benennen Sie es als File to database - With Cedilla delimiter . Deaktivieren Sie die erste Datenflussaufgabe.

Konfigurieren Sie die zweite Datenflussaufgabe mit Flat File Source und OLE DB Destination

Doppelklicken Sie auf die Flatfile-Quelle, um den Flat File Source Editor zu öffnen . Auf dem Connection Managers Seite des Flat File Source Editor , wählen Sie den Verbindungsmanager für Flatfiles aus ProductListPrice_Cedilla und klicken Sie auf Spalten Seite zum Konfigurieren der Spalten. Klicken Sie auf OK .

Führen Sie das Paket aus. Alle Komponenten werden grün angezeigt, um anzuzeigen, dass der Prozess erfolgreich war, aber keine Zeilen verarbeitet werden. Sie können sehen, dass zwischen der Flat File Source keine Zeilennummern angegeben sind und OLE DB Destination

Klicken Sie auf Progress und Sie werden die folgende Warnmeldung bemerken.

[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.