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

SSIS-Aufgabe für inkonsistenten Import der Spaltenanzahl?

Aus dem Kopf heraus habe ich eine 50 %-Lösung für Sie.

Das Problem

SSIS wirklich kümmert sich um Metadaten, sodass Variationen darin tendenziell zu Ausnahmen führen. DTS war in diesem Sinne weitaus nachsichtiger. Dieser starke Bedarf an konsistenten Metadaten macht die Verwendung der Flat File Source mühsam.

Abfragebasierte Lösung

Wenn das Problem die Komponente ist, verwenden wir sie nicht. Was mir an diesem Ansatz gefällt, ist, dass es konzeptionell dasselbe ist wie das Abfragen einer Tabelle – die Reihenfolge der Spalten spielt keine Rolle, noch spielt das Vorhandensein zusätzlicher Spalten eine Rolle.

Variablen

Ich habe 3 Variablen erstellt, alle vom Typ String:CurrentFileName, InputFolder und Query.

  • InputFolder ist fest mit dem Quellordner verbunden. In meinem Beispiel ist es C:\ssisdata\Kipreal
  • CurrentFileName ist der Name einer Datei. Während der Entwurfszeit war es input5columns.csv aber das wird sich zur Laufzeit ändern.
  • Abfrage ist ein Ausdruck "SELECT col1, col2, col3, col4, col5 FROM " + @[User::CurrentFilename]

Verbindungsmanager

Richten Sie mit dem JET OLEDB-Treiber eine Verbindung zur Eingabedatei ein. Nachdem ich es wie im verlinkten Artikel beschrieben erstellt habe, habe ich es in FileOLEDB umbenannt und einen Ausdruck für den ConnectionManager von "Data Source=" + @[User::InputFolder] + ";Provider=Microsoft.Jet.OLEDB.4.0;Extended Properties=\"text;HDR=Yes;FMT=CSVDelimited;\";"

Kontrollfluss

Meine Ablaufsteuerung sieht aus wie eine Datenflussaufgabe, die in einem Foreach-Dateienumerator

verschachtelt ist

Foreach-Datei-Enumerator

Mein Foreach File-Enumerator ist so konfiguriert, dass er mit Dateien arbeitet. Ich habe einen Ausdruck in das Verzeichnis für @[User::InputFolder] eingefügt Beachten Sie, dass an diesem Punkt, wenn der Wert dieses Ordners geändert werden muss, er sowohl im Verbindungsmanager als auch im Dateienumerator korrekt aktualisiert wird. Wählen Sie bei „Dateinamen abrufen“ anstelle des standardmäßigen „Vollqualifiziert“ „Name und Erweiterung“

Weisen Sie auf der Registerkarte Variablenzuordnungen den Wert unserem @[User::CurrentFileName] zu Variable

An diesem Punkt ändert jede Iteration der Schleife den Wert von @[User::Query um den aktuellen Dateinamen widerzuspiegeln.

Datenfluss

Dies ist eigentlich das einfachste Stück. Verwenden Sie eine OLE DB-Quelle und verbinden Sie sie wie angegeben.

Verwenden Sie den FileOLEDB-Verbindungsmanager und ändern Sie den Datenzugriffsmodus in „SQL-Befehl aus Variable“. Verwenden Sie den @[User::Query] Variable darin, klicken Sie auf OK und Sie können mit der Arbeit beginnen.

Beispieldaten

Ich habe zwei Beispieldateien input5columns.csv und input7columns.csv erstellt. Alle Spalten von 5 befinden sich in 7, aber 7 hat sie in einer anderen Reihenfolge (col2 ist die Ordnungsposition 2 und 6). Ich habe alle Werte in 7 negiert, um deutlich zu machen, welche Datei bearbeitet wird.

col1,col3,col2,col5,col4
1,3,2,5,4
1111,3333,2222,5555,4444
11,33,22,55,44
111,333,222,555,444

und

col1,col3,col7,col5,col4,col6,col2
-1111,-3333,-7777,-5555,-4444,-6666,-2222
-111,-333,-777,-555,-444,-666,-222
-1,-3,-7,-5,-4,-6,-2
-11,-33,-77,-55,-44,-666,-222

Das Ausführen des Pakets führt zu diesen beiden Screenshots

Was fehlt

Ich kenne keine Möglichkeit, dem abfragebasierten Ansatz mitzuteilen, dass es in Ordnung ist, wenn eine Spalte nicht vorhanden ist. Wenn es einen eindeutigen Schlüssel gibt, könnten Sie Ihre Abfrage wahrscheinlich so definieren, dass sie nur die Spalten enthält, die müssen Seien Sie dort und führen Sie dann Suchen in der Datei durch, um zu versuchen, die Spalten zu erhalten, die sollten um dort zu sein und die Suche nicht fehlschlagen zu lassen, wenn die Spalte nicht existiert. Ziemlich klobig.