Wiederaufnehmbare Bulk-Imports in SQL Server aufbauen
Trennen Sie Rohdaten, typisierte Prüfung und Veröffentlichung, damit fehlerhafte Dateien und Wiederholungen keine halbfertigen Produktivdaten hinterlassen.
Ein schneller Bulk-Load ist nur ein Teil eines zuverlässigen Imports. Danach müssen Sie erklären können, welche Datensätze abgelehnt wurden, ob dieselbe Datei bereits verarbeitet wurde und ob Benutzer nur einen halben Datenbestand sehen. Eine Staging-Struktur beantwortet diese Fragen ausdrücklich.
Rohdaten und Herkunft sichern
Vergeben Sie eine stabile Batch-ID und speichern Sie Dateidentität, Inhaltshash, Eingangszeit und Parser-Version. Der Dateiname reicht nicht, weil ein Lieferant denselben Namen mit anderem Inhalt verwenden kann. Bewahren Sie Originalfelder und eine Quellkennung pro Datensatz auf, um Fehler nachvollziehen zu können.
Laden Sie zunächst in einen getrennten Staging-Bereich. BULK INSERT benötigt einen Pfad, den der SQL-Server-Rechner oder die konfigurierte Datenquelle erreichen kann. Ein Pfad auf dem Laptop des Analysten genügt nicht. Prüfen Sie Zugriffsidentität und Dateivertrag, einschließlich Kodierung, Trennzeichen in Anführungszeichen, eingebetteter Zeilenumbrüche und leerer Felder.
Physische Textzeilen sind bei CSV mit eingebetteten Umbrüchen nicht dasselbe wie logische Datensätze. Wenn genaue Quellpositionen wichtig sind, muss der Parser sie erfassen. Ein automatisch erzeugter Staging-Identitywert beweist nicht die ursprüngliche Reihenfolge.
Das Beispiel beginnt nach dem Dateiparsing und zeigt die Grenze zwischen Rohtext und fachlicher Prüfung. Es ist kein vollständiger CSV-Parser.
DECLARE @Raw TABLE
(
SourceRow int PRIMARY KEY,
CustomerText nvarchar(100),
DateText nvarchar(100),
AmountText nvarchar(100)
);
INSERT @Raw VALUES
(1, N'42', N'20260601', N'125.50'),
(2, N'bad', N'20260602', N'20.00'),
(3, N'43', N'20260230', N'15.00'),
(4, N'44', N'20260603', N''),
(5, N'45', N'20260604', N'-7.00');
SELECT r.*,
TRY_CONVERT(int, NULLIF(LTRIM(RTRIM(CustomerText)), N'')) AS CustomerId,
TRY_CONVERT(date, NULLIF(LTRIM(RTRIM(DateText)), N''), 112) AS InvoiceDate,
TRY_CONVERT(decimal(19,4), NULLIF(LTRIM(RTRIM(AmountText)), N'')) AS Amount
INTO #Parsed
FROM @Raw AS r;
SELECT SourceRow, CustomerId, InvoiceDate, Amount,
CASE
WHEN CustomerId IS NULL OR CustomerId <= 0 THEN N'Invalid customer'
WHEN InvoiceDate IS NULL THEN N'Invalid date'
WHEN Amount IS NULL OR Amount <= 0 THEN N'Invalid amount'
ELSE N'Accepted'
END AS ValidationResult
FROM #Parsed
ORDER BY SourceRow;
DROP TABLE #Parsed;
Nur Datensatz 1 wird akzeptiert. Datensatz 2 hat eine ungültige Kundennummer, 3 ein unmögliches Datum, 4 einen leeren und 5 einen negativen Betrag. NULLIF verhindert, dass ein leerer Zahlenwert als brauchbare Zahl behandelt wird. Stil 112 legt YYYYMMDD als Datumsvertrag fest.
Ablehnungen nachvollziehbar speichern
TRY_CONVERT trennt viele Konvertierungsprobleme von einem Abbruch des gesamten Batches. Erfolgreiche Konvertierung bedeutet jedoch nicht fachliche Gültigkeit. Das Beispiel akzeptiert positive IDs, ohne die Existenz des Kunden zu beweisen. Prüfen Sie vor der Veröffentlichung gegen den erlaubten Kundenbestand.
Auch eine Umwandlung nach decimal kann zusätzliche Nachkommastellen runden. Wenn solche Eingaben verboten sind, benötigen Sie eine Prüfung der ursprünglichen Darstellung oder einen Vergleich mit einer zulässigen genaueren Repräsentation. Eine passende Zielspalte ersetzt den Eingabevertrag nicht.
CASE zeigt zur Übersicht nur den ersten Fehler einer Zeile. Eine produktive Fehlertabelle kann mehrere Gründe speichern: Batch-ID, Quellkennung, Feld, Fehlercode und Originalwert. Regeln Sie Zugriff und Aufbewahrung passend zum Inhalt. Eine allgemeine Meldung wie 'Import fehlgeschlagen' liefert der Unterstützung zu wenig Informationen.
Prüfen Sie Duplikate sowohl innerhalb des Batches als auch gegen den fachlichen Zielschlüssel. Legen Sie fest, ob Wiederholungen abgelehnt, ersetzt oder bewusst aggregiert werden. DISTINCT als Mittel gegen eine Unique-Verletzung kann einen Lieferantenfehler oder relevante Unterschiede verdecken.
Gleichen Sie Rohdatensätze, Parserfehler, fachliche Ablehnungen, akzeptierte und veröffentlichte Zeilen ab. Definieren Sie die Kategorien so, dass mehrere Fehler derselben Zeile die Anzahl nicht vervielfachen. Speichern Sie diese Bilanz dauerhaft beim Batch.
Veröffentlichung und Wiederanlauf festlegen
Entscheiden Sie zwischen vollständiger Annahme und erlaubter Teilannahme. Für einen atomaren Import schließen Sie die Vorprüfung ab, bevor eine kurze Transaktion Daten übernimmt und den Batch als veröffentlicht markiert. Zielconstraints bleiben nötig, weil sich Referenzdaten seit der Vorprüfung geändert haben können.
Erzwingen Sie Eindeutigkeit der Batch- oder Operationsidentität. Nach Verbindungsverlust hinter einem erfolgreichen Commit muss eine Wiederholung den bestehenden Ausgang erkennen. Markierung und Datenänderung gehören in dieselbe Transaktion.
Bei großen Imports können begrenzte Teilmengen nötig sein. Dann muss der Wiederanlauf abgeschlossene Teile erkennen und jeden Teil wiederholbar verarbeiten. Alternativ bleiben Daten bis zur finalen Freigabe unsichtbar, sofern wirklich jeder Leser diese Freigabe berücksichtigt.
Messen Sie Parsing, Prüfjoins, Logwachstum, Indexpflege und Veröffentlichung gemeinsam. Bewahren Sie abgelehnte Eingaben für Korrektur und erneute Verarbeitung auf und löschen Sie sie nach einer definierten Frist. Ein guter Import erklärt seinen Ausgang und lässt sich sicher fortsetzen.
Technische Referenzen: Microsoft Learn: BULK INSERT · Microsoft Learn: TRY_CONVERT.