Rollbacks und Commits in gespeicherten Prozeduren und Triggern

Die Ausführung einer Transact-SQL-Anweisung vom Typ ROLLBACK TRANSACTION oder COMMIT TRANSACTION innerhalb einer gespeicherten Prozedur oder innerhalb eines Triggers ist zwar möglich, kann jedoch Fehler verursachen.

In gespeicherten Prozeduren

Wenn @@TRANCOUNT einen anderen Wert beim Beenden als beim Ausführungsbeginn einer gespeicherten Prozedur aufweist, tritt ein informatorischer Fehler (266) auf. Dies kann in zwei Varianten geschehen:

  • Eine gespeicherte Prozedur wird mit einem @@TRANCOUNT von 1 oder größer aufgerufen, und die gespeicherte Prozedur führt eine ROLLBACK TRANSACTION-Anweisung aus. @@TRANCOUNT wird auf 0 reduziert und verursacht einen Fehler 266, wenn die gespeicherte Prozedur abgeschlossen wird.

  • Eine gespeicherte Prozedur wird mit einem @@TRANCOUNT von 1 oder größer aufgerufen, und die gespeicherte Prozedur führt eine COMMIT TRANSACTION-Anweisung aus. @@TRANCOUNT wird um 1 reduziert und verursacht einen Fehler 266, wenn die gespeicherte Prozedur abgeschlossen wird. Wenn allerdings BEGIN TRANSACTION nach COMMIT TRANSACTION ausgeführt wird, tritt der Fehler nicht auf.

In Triggern

Ein Trigger arbeitet so, als ob eine ausstehende Transaktion aktiv wäre, wenn der Trigger ausgeführt wird. Dies trifft zu, wenn es sich bei der Anweisung, die den Trigger ausgelöst hat, um eine implizite oder explizite Transaktion handelt.

Wenn eine Anweisung im Autocommitmodus mit der Ausführung beginnt, liegt implizit eine BEGIN TRANSACTION-Anweisung vor, die das Wiederherstellen aller Änderungen ermöglicht, die von der Anweisung generiert wurden, falls ein Fehler festgestellt wird. Diese implizite Transaktion hat keinerlei Auswirkungen auf andere Anweisungen im Batch, da für sie beim Beenden der Anweisung entweder ein Commit oder ein Rollback ausgeführt wird. Die implizite Transaktion ist jedoch noch aktiv, wenn ein Trigger aufgerufen wird.

Bei der Ausführung eines Triggers wird eine implizite Transaktion gestartet. Wenn die Ausführung eines Triggers mit @@TRANCOUNT = 0 abgeschlossen wird, tritt der Fehler 3609 auf, und der Batch wird beendet. Bei Auslösung einer BEGIN TRANSACTION-Anweisung in einem Trigger wird eine geschachtelte Transaktion erstellt. In dieser Situation gilt die ausgeführte COMMIT TRANSACTION-Anweisung nur für die geschachtelte Transaktion.

Bei Verwendung von ROLLBACK TRANSACTION in einem Trigger müssen Sie das folgende Verhalten beachten:

  • Für alle Datenänderungen, die bis zu diesem Zeitpunkt in der aktuellen Transaktion vorgenommen worden sind, wird ein Rollback ausgeführt, einschließlich aller Änderungen, die vom Trigger vorgenommen wurden.

  • Der Trigger setzt die Ausführung aller verbleibenden Anweisungen nach der ROLLBACK-Anweisung fort. Wenn durch eine dieser Anweisungen Daten geändert werden, wird für die Änderungen kein Rollback ausgeführt.

  • Ein ROLLBACK in einem Trigger schließt alle Cursor und hebt deren Zuordnung auf, die in dem Batch mit der Anweisung, die den Trigger auslöste, deklariert und geöffnet wurden. Dazu gehören auch die in gespeicherten Prozeduren deklarierten und geöffneten Cursor, die von dem Batch aufgerufen wurden, der den Trigger ausgelöst hat. Cursor, die in einem Batch vor demjenigen Batch, der den Trigger ausgelöst hat, deklariert wurden, werden einfach geschlossen. Davon ausgenommen sind STATIC- oder INSENSITIVE-Cursor, die offen bleiben, wenn Folgendes gilt:

    • CURSOR_CLOSE_ON_COMMIT ist auf OFF festgelegt.

    • Der statische Cursor ist ein synchroner oder ein vollständig aufgefüllter asynchroner Cursor.

Anstelle der Verwendung von ROLLBACK TRANSACTION kann die SAVE TRANSACTION-Anweisung zum Ausführen eines teilweisen Rollbacks in einem Trigger verwendet werden.