Der Bedarf, fehlerhafte Zeilen beim massenhaften Import zu protokollieren, entstand praktisch sofort nach der Einführung automatisierter Ladevorgänge großer Datenmengen in Datenbanken. Traditionell führte jede Verletzung von Einschränkungen (z. B. von Datentypen, Constraints) dazu, dass der gesamte Importprozess aufgrund einer einzigen fehlerhaften Zeile unterbrochen wurde - mit der Folge, dass sowohl korrekte als auch inkorrekte Datensätze verloren gingen.
Das Problem besteht darin, nicht nur so viele korrekte Daten wie möglich zu laden, sondern auch eine Überprüfung und detaillierte Beschreibung der Fehler für eine spätere manuelle Nachbearbeitung zu hinterlassen, anstatt einfach "alles zurückzusetzen".
Lösung: Für einige DBMS (z. B. PostgreSQL, SQL Server mit SSIS, Oracle mit EXTERNAL TABLES) gibt es Mechanismen zum Laden mit Trennung der fehlerhaften Zeilen. Für einen universellen Ansatz verwendet man Staging-Tabellen und eine post-upload Validierung mit OUTER JOIN und NOT EXISTS sowie angehängte "Log-Tabellen", in die manuelle Datensätze für problematische Zeilen geschrieben werden.
Beispiel-Code:
-- 1. Laden aller Daten in eine temporäre Staging-Tabelle BULK INSERT staging_payments FROM 'payments.csv' WITH (...) -- 2. Filtern der gültigen Datensätze INSERT INTO payments (id, amount, ...) SELECT id, amount, ... FROM staging_payments WHERE amount > 0 AND status IN ('approved', 'pending'); -- 3. Protokollierung fehlerhafter Zeilen in eine separate Tabelle INSERT INTO import_errors (row_data, error_desc) SELECT *, 'Ungültiger Status oder negativer Betrag' FROM staging_payments WHERE amount <= 0 OR status NOT IN ('approved', 'pending');
Wichtige Merkmale:
Kann alles über ON ERROR RESUME NEXT innerhalb von SQL implementiert werden?
Der SQL-Standard enthält eine solche Anweisung für massive Importoperationen nicht. In den meisten Fällen wird der Fehlerbericht in externen Tools oder in Log-Tabellen erstellt, wie oben beschrieben.
Kann man eine Transaktion verwenden, um nur fehlerhafte Zeilen zurückzusetzen?
Ein Rollback einer Transaktion setzt alle Zeilen auf einmal zurück (Atomicity). Teilweise Speicherung ist nur möglich, wenn zuerst in eine Staging-Tabelle geladen wird, wonach manuell ein Commit der erfolgreichen und ein Log der fehlgeschlagenen Zeilen durchgeführt wird.
Warum ist es ineffizient, jeden INSERT-Fehler durch TRY/CATCH in einer Schleife für jede Zeile zu erfassen?
Die sequenzielle Verarbeitung von Millionen von Zeilen über einzelne INSERT + TRY/CATCH führt zu einem katastrophalen Rückgang der Leistung im Vergleich zu Batch- oder BULK INSERT + Nachprüfen nach dem Laden.
Ein Unternehmen lud Zehntausende von Zeilen über ein INSERT-Skript hoch, und bei einem Fehler aufgrund eines einzigartigen Schlüssels wurde die gesamte Batch zurückgesetzt. Dies führte zu Ausfallzeiten und Datenverlust.
Vorteile:
Die Verwendung von Staging-Tabellen, Fehlerprotokollierung und die Trennung der eingehenden Daten in Kategorien "gültig/ungültig" ermöglichten eine schnellere Importierung, Speicherung und automatische Analyse von Fehlern.
Vorteile: