Ich wurde gerade von etwas in TSQL überrascht. Ich dachte, wenn xact_abort aktiviert ist, rufe ich so etwas an
raiserror('Something bad happened', 16, 1);
würde die Ausführung der gespeicherten Prozedur (oder eines beliebigen Stapels) stoppen.
Aber meine ADO.NET-Fehlermeldung hat genau das Gegenteil bewiesen. Ich habe sowohl die Raiserror-Fehlermeldung in der Ausnahmemeldung als auch die nächste Meldung erhalten.
Dies ist meine Problemumgehung (was sowieso meine Gewohnheit ist), aber es scheint nicht notwendig zu sein:
if @somethingBadHappened
begin;
raiserror('Something bad happened', 16, 1);
return;
end;
Die Dokumente sagen dies:
Wenn SET XACT_ABORT aktiviert ist und eine Transact-SQL-Anweisung einen Laufzeitfehler auslöst, wird die gesamte Transaktion beendet und zurückgesetzt.
Bedeutet das, dass ich eine explizite Transaktion verwenden muss?
sql
sql-server
tsql
Eric Z Bart
quelle
quelle
RAISERROR
wird tatsächlich die Ausführung beenden, wenn der Schweregrad auf 17 oder 18 anstatt auf 16 eingestellt ist.RAISERROR
wird in der Tat nicht die Ausführung beenden, wenn der Schweregrad auf 17 oder 18 statt 16 eingestellt ist.Antworten:
Dies ist By Design TM , wie Sie in Connect anhand der Antwort des SQL Server-Teams auf eine ähnliche Frage sehen können:
Ja, dies ist ein Problem für einige, die gehofft haben, dass
RAISERROR
ein hoher Schweregrad (wie16
) mit einem SQL-Ausführungsfehler identisch ist - dies ist jedoch nicht der Fall.Ihre Problemumgehung ist genau das, was Sie tun müssen, und die Verwendung einer expliziten Transaktion hat keine Auswirkungen auf das Verhalten, das Sie ändern möchten.
quelle
Wenn Sie einen Try / Catch-Block verwenden, führt eine Raiserror-Fehlernummer mit dem Schweregrad 11-19 dazu, dass die Ausführung zum Catch-Block springt.
Jeder Schweregrad über 16 ist ein Systemfehler. Um den folgenden Code zu demonstrieren, wird ein Try / Catch-Block eingerichtet und eine gespeicherte Prozedur ausgeführt, von der wir annehmen, dass sie fehlschlägt:
Angenommen, wir haben eine Tabelle [dbo]. [Fehler], um Fehler zu speichern. Angenommen, wir haben eine gespeicherte Prozedur [dbo]. [AssumeThisFails], die fehlschlägt, wenn wir sie ausführen
quelle
Verwenden Sie
RETURN
sofort danachRAISERROR()
und es wird die Prozedur nicht weiter ausführen.quelle
rollback transaction
anrufenreturn
.Wie in den Dokumenten für angegeben
SET XACT_ABORT
, sollte dieTHROW
Anweisung anstelle von verwendet werdenRAISERROR
.Die beiden verhalten sich etwas unterschiedlich . Wenn
XACT_ABORT
jedoch ON eingestellt ist, sollten Sie immer denTHROW
Befehl verwenden.quelle