Historisch war die Fehlerbehandlung in SQL nur darauf beschränkt, die Transaktion nach einem fatalen Fehler zurückzusetzen. Mit der Entwicklung der Geschäftslogik wird es jedoch zunehmend erforderlich, Fehler genau zu protokollieren, nur die Änderungen zurückzusetzen, die vorgenommen wurden, sowie die Möglichkeit geschachtelter Prozeduraufrufe (nested transactions).
Das Problem besteht darin, dass nicht alle DBMS vollständig geschachtelte Transaktionen unterstützen (zum Beispiel handelt es sich bei MS SQL Server eher um Ebenen von gespeicherten Punkten SAVEPOINT und nicht um echte Transaktionen), und bei Fehlerausnahmen kann die Ausführung vor der notwendigen Bereinigung unterbrochen werden, wenn die Mechanismen TRY/CATCH oder ähnliche nicht verwendet werden.
Lösung: Verwenden Sie TRY/CATCH-Konstruktionen (oder ähnliche), SAVEPOINT für die Verschachtelung und konfigurieren Sie das Verhalten von Prozeduren bei Fehlern (zum Beispiel SET XACT_ABORT in SQL Server).
Beispielcode (MS SQL Server):
BEGIN TRY BEGIN TRANSACTION -- Operationen EXEC dbo.InnerProcedure COMMIT TRANSACTION END TRY BEGIN CATCH IF @@TRANCOUNT > 0 ROLLBACK TRANSACTION -- Fehlerprotokollierung INSERT INTO error_log VALUES (ERROR_NUMBER(), ERROR_MESSAGE(), GETDATE()) END CATCH
Wesentliche Merkmale:
Tritt bei einem Fehler in einer geschachtelten Transaktion ein echter Rollback aller Änderungen ein?
In den meisten DBMS sind geschachtelte Transaktionen keine separaten Transaktionen, sondern Rückgabepunkte (SAVEPOINT). Bei einem allgemeinen Rollback werden alle Änderungen bis zur anfänglichen (äußeren) Transaktion zurückgesetzt.
Was passiert, wenn man verpasst, @@TRANCOUNT zu überprüfen und ROLLBACK außerhalb einer aktiven Transaktion ausführt?
Ein Fehler wird ausgelöst — es gibt keine aktive Transaktion zum Zurücksetzen. Überprüfen Sie immer @@TRANCOUNT > 0 vor ROLLBACK.
Funktionieren Trigger und Cursor in TRY/CATCH?
Ja, aber Fehler in einem Trigger können zu einem Übergang in CATCH führen und die gesamte Transaktion zurücksetzen. Fehlerbehandlung muss sowohl im Körper der Prozedur als auch in aufgerufenen Objekten (Prozeduren, Triggern) vorgesehen werden.
Mehrere geschachtelte Prozeduren, jede verwendet BEGIN TRANSACTION / COMMIT ohne TRY/CATCH, bei einem Fehler wurden einige Daten geändert, andere nicht.
Vorteile:
Nachteile:
Die gesamte Logik ist in TRY/CATCH gewickelt, geschachtelte Prozeduren verwenden SAVEPOINT oder arbeiten innerhalb einer äußeren Transaktion, alle Fehler werden protokolliert.
Vorteile:
Nachteile: