Importe ohne Handarbeit

Importe, die auch dann laufen, wenn du im Urlaub bist

Die Technik des Ladens ist der einfache Teil. Der Unterschied entsteht bei Datentypen, Fehlerzeilen und der Frage, wer erfährt, dass der Lauf heute Nacht nichts getan hat.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Seit 1997 am Markt Kleine Gruppen Präsenz und Live-Online Zertifizierte Trainer
Worum es geht

Der Import läuft, bis sich in der Quelle eine Kleinigkeit ändert

Der typische Ausgangspunkt: Eine CSV-Datei aus einem Vorsystem kommt jeden Monat per SFTP, jemand öffnet den Import- und Export-Assistenten im SQL Server Management Studio, klickt sich durch und lädt sie in eine Tabelle. Das dauert zehn Minuten und funktioniert. Zwölfmal im Jahr, plus die Nacharbeiten, wenn zwischendurch jemand anderes einspringen muss und die Klickfolge nicht kennt.

Teuer wird das an zwei Stellen. Erstens raten Assistent und Flat File Source die Datentypen aus den ersten Zeilen der Datei. Eine Artikelnummer wie 00734 landet als Ganzzahl in der Zieltabelle, die führende Null ist weg, und der Abgleich mit dem Vorsystem verliert ab diesem Monat Treffer. Ein Feld, das bisher nie länger als 50 Zeichen war, sprengt beim nächsten Mal die Spaltenbreite und der ganze Lauf bricht ab. Zweitens ist der Abbruch noch der freundliche Fall. Unangenehmer ist der Lauf, der scheinbar durchgeht, dabei aber nur 4.800 von 5.000 Zeilen schreibt, weil zweihundert Datensätze in die Fehlerausgabe gelaufen sind, die niemand ausliest.

Wer die Handarbeit durch einen geplanten Auftrag ersetzt, verschiebt das Problem, wenn er die Protokollierung auslässt. Ein Agent-Auftrag, der nachts um zwei fehlschlägt, meldet sich von allein bei niemandem. Der Fehler fällt dann auf, wenn jemand in der Fachabteilung merkt, dass in der Auswertung seit drei Wochen dieselben Zahlen stehen.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt
Schritt für Schritt

Der Weg von der Handarbeit zum geplanten Auftrag

Die Reihenfolge ist wichtiger, als sie aussieht. Wer den Auftrag einplant, bevor die Fehlerbehandlung steht, automatisiert vor allem das Erzeugen unbemerkter Lücken.

  1. 1

    Die Quelle festnageln

    Klär Trennzeichen, Textqualifizierer, Zeilenumbruch und Kodierung, bevor du irgendetwas baust. Öffne die Datei in einem Editor, der die Kodierung anzeigt, und sieh dir die letzten Zeilen an, nicht die ersten. Vereinbare mit dem liefernden System ein festes Namensmuster mit Datum, damit der Auftrag die richtige Datei findet und eine fehlende Lieferung auffällt.

    Geschafft, wenn: Du kannst benennen, was in Zeile 1 steht, wie eine leere Zahl aussieht und welche Kodierung die Datei hat.

  2. 2

    In eine Staging-Tabelle laden

    Leg eine Zwischentabelle an, in der alle Spalten großzügig als NVARCHAR definiert sind. Dort geht das Laden fast immer durch, und du siehst die Daten so, wie sie geliefert wurden. Der Import selbst läuft je nach Fall über BULK INSERT mit einer Formatdatei, über bcp oder über die Flat File Source in einem SSIS-Datenfluss.

    Geschafft, wenn: Die Zeilenzahl in der Staging-Tabelle stimmt mit der Zeilenzahl der Datei überein.

  3. 3

    Typen und Regeln beim Übernehmen prüfen

    Erst beim Weg von Staging ins Ziel wandelst du um und prüfst. TRY_CONVERT liefert NULL statt eines Abbruchs, wenn ein Datum nicht passt, und damit kannst du die betroffenen Zeilen zählen und ansehen. Beträge mit Komma als Dezimaltrennzeichen und Datumsangaben im Format MM/TT/JJJJ sind die beiden Klassiker, an denen deutsche und amerikanische Vorsysteme aneinandergeraten.

    Geschafft, wenn: Eine Abfrage auf die Staging-Tabelle zeigt null nicht wandelbare Werte.

  4. 4

    Fehlerzeilen sichtbar ablegen

    Häng an die OLE DB Destination eine Fehlerausgabe und stell sie von Fail Component auf Redirect Row. Die Fehlerausgabe liefert ErrorCode und ErrorColumn nur als Zahlen; den Klartext dazu holst du über eine Skriptkomponente, die GetErrorDescription auf den ErrorCode anwendet. Schreib das Ergebnis mit Ladezeitpunkt und Dateiname in eine Quarantänetabelle. Entscheidend ist dabei die Einstellung Maximale Commit-Größe beim Einfügen: Beim schnellen Laden wird der gesamte Commit-Block umgeleitet, in dem eine Zeile scheitert. Erst der Wert 1 isoliert die einzelne Zeile, und Zeilen pro Batch ändert daran nichts, das ist nur ein Hinweis an den Optimierer.

    Geschafft, wenn: Eine fehlerhafte Testzeile landet in der Quarantäne, die restlichen Zeilen sind trotzdem geladen.

  5. 5

    Das Paket in den Katalog stellen

    Stell das Projekt auf das Projektbereitstellungsmodell um, setz die Schutzebene auf DontSaveSensitive und leg Verbindungszeichenfolgen und Pfade als Projektparameter an. Nach dem Bereitstellen im SSISDB füllst du die Parameter über eine Umgebung. Das ist der Punkt, an dem die meisten Automatisierungen scheitern: Ein Paket mit der Voreinstellung EncryptSensitiveWithUserKey läuft in Visual Studio einwandfrei und im Agent-Auftrag gar nicht, weil der Schlüssel am Benutzerprofil des Entwicklers hängt.

    Geschafft, wenn: Das Paket startet aus dem SSISDB heraus, ohne dass jemand ein Kennwort nachträgt.

  6. 6

    Den Auftrag mit passenden Rechten planen

    Leg im SQL Server Agent einen Auftrag mit dem Schritttyp SQL Server Integration Services-Paket an. Kommt die Datei von einer Freigabe, brauchst du eine Anmeldeinformation mit einem Konto, das dort lesen darf, und darauf einen Proxy für das Subsystem SSIS. Plan den Lauf nicht auf die volle Stunde, sondern versetzt zu Sicherung und Indexpflege.

    Geschafft, wenn: Der Auftrag läuft zum geplanten Zeitpunkt durch, ohne dass jemand angemeldet ist.

  7. 7

    Benachrichtigung und Aufbewahrung einrichten

    Richte Datenbank-E-Mail ein, leg einen Operator an und verknüpf ihn im Auftrag mit der Aktion bei Fehler. Ergänze einen Schritt, der die geladene Zeilenzahl gegen den Vormonat vergleicht und bei null Zeilen bewusst fehlschlägt, denn ein leerer Lauf gilt technisch als Erfolg. Prüf außerdem die Katalogeigenschaften: Der Aufbewahrungszeitraum steht mit 365 Tagen recht hoch, und die SSISDB wächst still mit.

    Geschafft, wenn: Ein absichtlich herbeigeführter Fehlschlag erzeugt innerhalb weniger Minuten eine E-Mail.

Sechs Stationen vom Klick zum geplanten Lauf

  1. 01 Die Quelldatei landet an einem festen Ort mit festem Namensmuster.
  2. 02 Der Lauf schreibt zuerst in eine Staging-Tabelle, nie direkt ins Ziel.
  3. 03 Spalten mit führenden Nullen bekommen einen Texttyp, keinen Zahlentyp.
  4. 04 Abgewiesene Zeilen gehen in eine Quarantänetabelle statt in den Abbruch.
  5. 05 Der SQL Server Agent startet das Paket über einen Proxy mit Dateirechten.
  6. 06 Erfolg und Fehlschlag lösen beide eine Nachricht an einen Operator aus.
Was du mitnimmst

Was du danach ohne Rückfragen selbst aufsetzt

Ein belastbarer Import besteht aus vier Entscheidungen, die du einmal triffst und danach nicht mehr anfasst: das Zielformat der Spalten, die Regel für Zeilen, die nicht passen, der Auslöser für den Lauf und der Weg, auf dem ein Fehlschlag bei einem Menschen ankommt. Wenn diese vier Punkte stehen, ist der Rest tatsächlich nur noch Ladetechnik.

Das Ladeverfahren zur Wiederholrate wählen

Für einen einmaligen Stand genügt BULK INSERT oder bcp mit einer Formatdatei. Sobald dieselbe Datei regelmäßig wiederkommt oder mehrere Quellen zusammenlaufen, baust du ein SSIS-Paket, weil du dort Fehlerbehandlung und Protokoll mitbekommst.

Kodierung und Datentypen festschreiben

Du setzt CODEPAGE = '65001' für UTF-8-Dateien und legst in der Flat File Source jede Spalte selbst fest, statt die Vorschlagswerte zu übernehmen. Nummern mit führenden Nullen werden DT_STR oder DT_WSTR, nie ein Ganzzahltyp.

Fehlerzeilen umleiten statt abbrechen

Du hängst an die Zielkomponente eine Fehlerausgabe mit Redirect Row und schreibst die abgewiesenen Zeilen samt ErrorCode und ErrorColumn in eine Quarantänetabelle. Der Lauf endet dann mit einem Ergebnis und nicht mit einem Abbruch mitten im Bestand.

Den Ladevorgang wiederholbar machen

Du lädst zuerst in eine Staging-Tabelle, prüfst dort die Zeilenzahl und übernimmst erst danach in die Zieltabelle. Ein zweiter Lauf derselben Datei darf keine doppelten Datensätze erzeugen, dafür brauchst du einen fachlichen Schlüssel und MERGE oder ein vorheriges Löschen des Zeitraums.

Den Auftrag mit den richtigen Rechten starten

Der SQL Server Agent läuft unter einem eigenen Konto, das an die Quelldateien in der Regel nicht herankommt. Du legst dafür eine Anmeldeinformation und einen Proxy an, statt dem Dienstkonto Rechte auf dem Dateiserver zu geben.

Den stillen Fehlschlag ausschließen

Du richtest Datenbank-E-Mail ein, hinterlegst einen Operator und verknüpfst ihn mit dem Auftrag. Zusätzlich prüfst du regelmäßig catalog.executions im SSISDB, weil ein Paket auch mit Warnungen und null geladenen Zeilen als erfolgreich gilt.

KI-generiertDieses Bild wurde mit KI erzeugt · Yves Hoppe / KI / cmt

BULK INSERT, bcp oder SSIS: die Entscheidung hängt an der Wiederholrate

BULK INSERT ist eine T-SQL-Anweisung und liest eine Datei ein, die aus Sicht der Datenbank-Engine erreichbar ist. Das heißt bei einer Instanz auf einem Server: aus Sicht des Dienstkontos, nicht aus deiner. Ein Pfad wie C:\import\daten.csv verweist auf die Platte des Servers, nicht auf deinen Rechner, und ein UNC-Pfad funktioniert nur, wenn das Dienstkonto auf der Freigabe lesen darf. Die Feinheiten steuerst du über FIELDTERMINATOR, ROWTERMINATOR, FIRSTROW für die Kopfzeile und CODEPAGE. Für UTF-8 setzt du CODEPAGE = '65001', ohne diese Angabe werden Umlaute zu Ersatzzeichen.

bcp ist das Kommandozeilenwerkzeug dazu und kann in beide Richtungen, also auch exportieren. Sein eigentlicher Vorteil ist die Formatdatei: Mit bcp erzeugst du einmal eine XML-Formatdatei, die Spaltenreihenfolge, Länge und Typ festhält, und danach ist der Aufbau der Datei dokumentiert und nicht mehr Auslegungssache. Wenn die Quelle später eine Spalte ergänzt, scheitert der Import mit einer klaren Meldung, statt die Werte um eine Position verschoben zu schreiben.

SSIS lohnt sich, sobald mehr als das reine Laden dazugehört: mehrere Quellen, Nachschlagen gegen Stammdaten, Umleiten fehlerhafter Zeilen, ein Ablauf mit Reihenfolge und Bedingungen. Der Import- und Export-Assistent im Management Studio erzeugt übrigens genau so ein Paket. Du kannst im letzten Schritt statt Sofort ausführen auch Speichern wählen und hast damit einen Ausgangspunkt, den du im Visual-Studio-Projekt weiterbaust, statt bei null anzufangen.

Die Datentyperkennung ist die häufigste Fehlerquelle

Die Flat File Source schlägt Datentypen vor, indem sie in die Datei hineinschaut, und zwar standardmäßig nur in die ersten Zeilen. Über Vorgeschlagene Typen kannst du die Zahl der geprüften Zeilen erhöhen, aber die eigentliche Antwort lautet: nicht raten lassen. Eine Spalte, die eine Nummer enthält, mit der niemand rechnet, ist Text. Postleitzahlen, Artikelnummern, Kostenstellen und Kundennummern gehören ausnahmslos in diese Gruppe, sonst verschwinden führende Nullen unwiderruflich.

Die Längenangabe ist die zweite Falle. Der Vorschlag lautet oft 50 Zeichen, weil in den geprüften Zeilen nichts Längeres stand. Kommt später ein Firmenname mit 63 Zeichen, bricht der Datenfluss mit einer Meldung über Kürzung ab. Deshalb ist der Umweg über eine Staging-Tabelle mit weiten NVARCHAR-Spalten so nützlich: Das Laden geht durch, und du siehst mit einer Abfrage auf MAX(LEN(spalte)), wie breit die Zielspalte wirklich sein muss.

Beim Weg von Staging ins Ziel arbeitest du mit TRY_CONVERT und TRY_CAST statt mit CONVERT. Beide liefern NULL, wenn die Umwandlung nicht gelingt, statt die Anweisung abzubrechen. Damit kannst du vorab zählen, wie viele Zeilen betroffen sind, und sie dir ansehen. Bei Datumsangaben gib den Stil mit an, TRY_CONVERT(date, spalte, 104) liest deutsches TT.MM.JJJJ, Stil 101 liest amerikanisches MM/TT/JJJJ. Ohne Stilangabe entscheidet die Spracheinstellung der Anmeldung, und die ist bei einem Agent-Auftrag oft eine andere als in deiner Sitzung im Management Studio.

Was ein zweiter Lauf mit denselben Daten anrichtet

Automatisierte Importe werden früher oder später doppelt ausgeführt, weil jemand den Auftrag von Hand nachstartet oder das Vorsystem eine Datei erneut liefert. Wenn der Ladevorgang nur einfügt, stehen die Datensätze danach zweimal in der Tabelle, und jede Summe darüber ist falsch. Der saubere Weg führt über einen fachlichen Schlüssel, also die Kombination aus Feldern, die einen Datensatz eindeutig macht, und darauf entweder MERGE oder das Muster, den betroffenen Zeitraum vor dem Laden zu löschen.

MERGE fasst Einfügen, Aktualisieren und Löschen in einer Anweisung zusammen und braucht als Grundlage einen eindeutigen Index auf dem Schlüssel der Zieltabelle. Ohne diesen Index läuft die Anweisung zwar, kann aber bei doppelten Schlüsseln in der Quelle mit einer Fehlermeldung abbrechen. Prüf deshalb vorher in der Staging-Tabelle mit GROUP BY und HAVING COUNT(*) > 1, ob die Quelle den Schlüssel überhaupt eindeutig hält. Bei Lieferungen aus Fremdsystemen ist die Antwort erstaunlich oft nein.

Die einfachere Variante ist das Löschen und Neuladen eines Zeitraums, etwa aller Datensätze des Vormonats vor dem Einspielen der neuen Datei. Das ist leichter zu verstehen und leichter zu prüfen, verlangt aber, dass die Datei den Zeitraum wirklich vollständig enthält. Bei Partitionierung gibt es dafür den eleganten Weg über SWITCH: Du lädst in eine leere Tabelle mit gleicher Struktur und tauschst die Partition, was unabhängig von der Datenmenge in Sekundenbruchteilen geschieht.

Ohne Protokoll ist der Auftrag kein Fortschritt

Der SQL Server Agent schreibt Verlaufseinträge, die im Management Studio unter Aufträge und Verlauf anzeigen liegen, mit Standardeinstellungen aber nach wenigen Läufen überschrieben werden. Die interessantere Quelle bei SSIS ist der Katalog selbst: catalog.executions zeigt Start, Ende und Status jeder Ausführung, catalog.execution_data_statistics die Zeilenzahl je Pfad im Datenfluss. Damit beantwortest du die Frage, ob heute Nacht wirklich Daten geflossen sind, und nicht nur, ob das Paket ohne Fehler endete.

Genau diese Unterscheidung ist der Kern. Ein Paket, dessen Quelldatei leer war, läuft erfolgreich durch und lädt null Zeilen. Aus Sicht des Agent ist das ein grüner Haken. Bau deshalb einen eigenen Prüfschritt: Vergleich die geladene Zeilenzahl mit dem Durchschnitt der letzten Läufe und lass den Auftrag mit RAISERROR bewusst fehlschlagen, wenn die Abweichung zu groß ist. Ein Import, der einmal ohne Grund um achtzig Prozent einbricht, ist immer eine Nachricht wert.

Für die Benachrichtigung brauchst du Datenbank-E-Mail mit einem Profil und einem Konto, danach einen Operator mit E-Mail-Adresse und im Auftrag unter Benachrichtigungen die Verknüpfung mit der Aktion Bei Fehler. Der Agent muss dazu wissen, welches Mailprofil er nutzt, das steht in den Eigenschaften des Agent unter Warnungssystem und verlangt nach dem Ändern einen Neustart des Dienstes. Diese eine Einstellung ist der Grund, warum eingerichtete Benachrichtigungen manchmal trotzdem nie ankommen.

Dazu passende Kurse

Wer den Datenfluss lieber einmal unter Anleitung aufbaut, statt sich durch Fehlermeldungen zu arbeiten, findet bei den SQL-Server-Schulungen zu den Integration Services den passenden Einstieg.

Weil die Ladestrecke nur so gut ist wie das Zielmodell dahinter, lohnt sich der Blick auf Kurse rund um Datenbanken und ihren Betrieb .

Wissen prüfen

Wie sicher bist du beim Thema wirklich?

Lesen fühlt sich schnell nach Können an. Ein kurzer Test zeigt dir, was davon schon sitzt und wo sich ein Kurs lohnt. Kostenlos, ohne Anmeldung, mit einer Erklärung zu jeder Antwort.

Super Schulung, in der der Trainer auch auf eigene Fragestellungen eingegangen ist.
PostgreSQL Datenbankentwicklung Aufbaukurs
Super Grundlagenschulung mit allen wichtigen Punkten und hilfreichen Tipps!
PostgreSQL Einführung und SQL Grundlagenkurs
Schön, sich 5 Tage ungestört mit Postgres beschäftigen zu können.
PostgreSQL für Administratoren Grundkurs

Häufige Fragen

Warum findet BULK INSERT meine Datei nicht, obwohl der Pfad stimmt?
Weil der Pfad aus Sicht der Datenbank-Engine ausgewertet wird, nicht aus deiner. C:\import\ meint das Laufwerk des Servers, auf dem die Instanz läuft. Liegt die Datei auf einer Freigabe, brauchst du einen UNC-Pfad und das Dienstkonto der Instanz muss dort lesen dürfen. Bei einer Instanz unter Linux gilt dasselbe für den Benutzer mssql und die Dateisystemrechte im Zielverzeichnis.
Aus Umlauten werden nach dem Import Fragezeichen oder Kästchen. Woran liegt das?
An der Kodierung. Bei BULK INSERT setzt du CODEPAGE = '65001' für UTF-8-Dateien, bei einer UTF-16-Datei zusätzlich DATAFILETYPE = 'widechar'. In der Flat File Source in SSIS stellst du die Codepage im Verbindungs-Manager ein und setzt bei Unicode-Dateien den entsprechenden Haken. Für das Ziel ist NVARCHAR die sichere Wahl, weil eine VARCHAR-Spalte sonst nur speichert, was ihre Kollation abbildet. Seit SQL Server 2019 gibt es dazu die Alternative einer UTF-8-Kollation auf der Spalte, dann speichert auch VARCHAR den vollen Zeichenvorrat und die Datei landet ohne Umweg im selben Format.
Mein SSIS-Paket läuft in Visual Studio, im Agent-Auftrag aber nicht. Was fehlt?
In neun von zehn Fällen die Schutzebene. Die Voreinstellung EncryptSensitiveWithUserKey verschlüsselt Kennwörter mit deinem Benutzerprofil, und das Dienstkonto des Agent kommt daran nicht heran. Stell das Projekt auf DontSaveSensitive um, stell es im SSISDB bereit und füll die Zugangsdaten über eine Umgebung. Der zweithäufigste Grund sind Dateirechte, dafür legst du eine Anmeldeinformation und darauf einen Proxy für das SSIS-Subsystem an.
Wie verhindere ich, dass ein einziger fehlerhafter Datensatz den ganzen Lauf kippt?
Über die Fehlerausgabe der Zielkomponente. Stell sie von Fail Component auf Redirect Row und leite die abgewiesenen Zeilen in eine Quarantänetabelle. Wichtig ist dabei die Einstellung Maximale Commit-Größe beim Einfügen: Beim schnellen Laden wird sonst der ganze Commit-Block umgeleitet und nicht nur die betroffene Zeile. Mit dem Wert 1 bekommst du die einzelne Zeile, allerdings zu Lasten der Ladegeschwindigkeit, deshalb lohnt sich ein zweiter Durchgang nur für den abgewiesenen Rest.
Persönlich für dich da

Deine Ansprechpartner

Du bist dir nicht sicher, welcher Kurs oder welches Level zu dir passt? Wir beraten dich persönlich und kostenlos.

Yves Hoppe

Yves Hoppe

Weiterbildung & Beratung

Hilft dir, aus dem Datenbanken-Programm den passenden Kurs für deinen Stand zu finden.

Norbert Jansen

Norbert Jansen

Beratung & Inhouse

Plant mit dir Inhouse-Trainings, die auf eure Abläufe und euren Datenbestand zugeschnitten sind.

Vom Klickmarathon zur Strecke, die von allein läuft

Bei cmt baust du eine solche Ladestrecke einmal komplett auf, von der Quelldatei über die Fehlerbehandlung bis zum geplanten Auftrag mit Benachrichtigung.