TL; DR / Zusammenfassung: Zu diesem Teil der Frage:
Ich sehe nicht, in welchen Fällen das Steuerelement CATCH
mit einer Transaktion übergeben werden kann, die festgeschrieben werden kann, wenn auf festgelegt XACT_ABORT
istON
.
Ich habe jetzt auf diese ziemlich viel Prüfung getan und ich kann keine Fälle , wo XACT_STATE()
Renditen 1
innerhalb eines CATCH
Blocks , wenn @@TRANCOUNT > 0
und der Sitzungs Eigenschaft XACT_ABORT
ist ON
. Und tatsächlich laut der aktuellen MSDN-Seite für SET XACT_ABORT :
Wenn SET XACT_ABORT auf ON gesetzt ist und eine Transact-SQL-Anweisung einen Laufzeitfehler auslöst, wird die gesamte Transaktion beendet und ein Rollback ausgeführt.
Diese Aussage scheint mit Ihrer Spekulation und meinen Ergebnissen übereinzustimmen.
Der MSDN-Artikel über SET XACT_ABORT
enthält ein Beispiel, in dem einige Anweisungen in einer Transaktion erfolgreich ausgeführt werden und andere fehlschlagen, wenn auf festgelegt XACT_ABORT
istOFF
Richtig, aber die Anweisungen in diesem Beispiel befinden sich nicht in einem TRY
Block. Die gleichen Aussagen innerhalb eines TRY
Blocks würde verhindern , dass nach wie vor der Ausführung für Aussagen nach der, die den Fehler verursacht hat , aber davon aus, dass XACT_ABORT
ist OFF
, wenn die Steuerung an die übergeben wird CATCH
Block die Transaktion noch in physisch gültig ist , dass alle vorherigen Änderungen ohne Fehler geschah und kann begangen werden, wenn das der Wunsch ist, oder sie können zurückgesetzt werden. Auf der anderen Seite, wenn XACT_ABORT
ist ON
dann werden alle Änderungen automatisch vor Rollback, und dann haben Sie die Wahl, entweder gegeben: a) Ausgabe einerROLLBACK
Dies ist meist nur eine Akzeptanz der Situation, da die Transaktion bereits zurückgesetzt wurde, abzüglich des Zurücksetzens @@TRANCOUNT
auf 0
, oder b) es wird ein Fehler angezeigt. Keine gute Wahl, oder?
Ein möglicherweise wichtiges Detail dieses Puzzles, das in dieser Dokumentation für nicht ersichtlich SET XACT_ABORT
ist, ist, dass es diese Sitzungseigenschaft und sogar diesen Beispielcode seit SQL Server 2000 gibt (die Dokumentation ist zwischen den Versionen nahezu identisch), und zwar vor dem TRY...CATCH
Konstrukt, das es gab in SQL Server 2005 eingeführt worden ist in dieser Dokumentation noch einmal suchen und Blick auf das Beispiel ( ohne die TRY...CATCH
) unter Verwendung XACT_ABORT ON
bewirkt eine sofortige Rollback der Transaktion: es gibt keine Transaktionszustand „Commit“ ( man beachte bitte , dass es keine Erwähnung ist alle "nicht festschreibbaren" Transaktionsstatus in dieser SET XACT_ABORT
Dokumentation).
Ich denke, es ist vernünftig zu folgern, dass:
- Durch die Einführung des
TRY...CATCH
Konstrukts in SQL Server 2005 wurde ein neuer Transaktionsstatus (dh "nicht festschreibbar") und die XACT_STATE()
Funktion zum Abrufen dieser Informationen erforderlich .
- Das Einchecken
XACT_STATE()
eines CATCH
Blocks ist nur dann sinnvoll, wenn beide der folgenden Bedingungen erfüllt sind:
XACT_ABORT
ist OFF
(sonst XACT_STATE()
sollte immer wiederkommen -1
und @@TRANCOUNT
wäre alles was du brauchst)
- Sie haben Logik im
CATCH
Block oder irgendwo in der Kette, wenn die Aufrufe verschachtelt sind, die eine Änderung vornimmt (eine COMMIT
oder sogar eine beliebige DML-, DDL- usw.-Anweisung), anstatt eine auszuführen ROLLBACK
. (Dies ist ein sehr untypischer Anwendungsfall.) ** Bitte beachten Sie den Hinweis unten im Abschnitt UPDATE 3 bezüglich einer inoffiziellen Empfehlung von Microsoft, immer XACT_STATE()
stattdessen zu prüfen @@TRANCOUNT
, und warum Tests zeigen, dass ihre Argumentation nicht aufgeht.
- Die Einführung des
TRY...CATCH
Konstrukts in SQL Server 2005 hat die XACT_ABORT ON
Sitzungseigenschaft größtenteils überholt, da sie ein höheres Maß an Kontrolle über die Transaktion bietet (zumindest haben Sie die Option dazu COMMIT
, sofern XACT_STATE()
diese nicht zurückgegeben wird -1
).
Eine andere Möglichkeit, dies zu betrachten, ist, vor SQL Server 2005 , XACT_ABORT ON
eine einfache und zuverlässige Möglichkeit, die Verarbeitung zu beenden, wenn ein Fehler auftrat, im Vergleich zur Überprüfung @@ERROR
nach jeder Anweisung.
- Der Dokumentations-Beispielcode für
XACT_STATE()
ist fehlerhaft oder bestenfalls irreführend, da angegeben wird, XACT_STATE() = 1
wann geprüft XACT_ABORT
wird ON
.
Der lange Teil ;-)
Ja, dieser Beispielcode auf MSDN ist etwas verwirrend (siehe auch: @@ TRANCOUNT (Rollback) vs. XACT_STATE ) ;-). Und ich halte es für irreführend, weil es entweder etwas zeigt, das keinen Sinn ergibt (aus dem Grund, den Sie fragen: Können Sie überhaupt eine "festschreibbare" Transaktion im CATCH
Block haben , wenn dies möglich XACT_ABORT
ist ON
), oder sogar, wenn dies möglich ist konzentriert sich immer noch auf eine technische Möglichkeit, die nur wenige jemals wollen oder brauchen werden, und ignoriert den Grund, warum es wahrscheinlicher ist, dass man sie braucht.
Wenn im TRY-Block ein schwerwiegender Fehler vorliegt, wird die Steuerung an CATCH übergeben. Wenn ich mich also im CATCH befinde, weiß ich, dass bei einer Transaktion ein Problem aufgetreten ist und dass in diesem Fall nur ein Rollback sinnvoll ist, nicht wahr?
Ich denke, es wäre hilfreich, wenn wir sicherstellen würden, dass wir in Bezug auf bestimmte Wörter und Konzepte auf derselben Seite sind:
"schwerwiegender Fehler": Nur um klar zu sein, TRY ... CATCH fängt die meisten Fehler ab. Die Liste der Objekte, die nicht abgefangen werden, befindet sich auf der verknüpften MSDN-Seite im Abschnitt "Fehler, die von einem TRY… CATCH-Konstrukt nicht betroffen sind".
"Wenn ich mich im CATCH befinde, weiß ich, dass eine Transaktion ein Problem hatte" (em phas wird hinzugefügt): Wenn Sie mit "Transaktion" die logische Arbeitseinheit meinen, die Sie durch Gruppieren von Anweisungen in einer expliziten Transaktion bestimmt haben, dann sehr wahrscheinlich ja. Ich denke, die meisten von uns DB-Leuten sind sich einig, dass Rollback "das einzig vernünftige" ist, da wir wahrscheinlich eine ähnliche Ansicht darüber haben, wie und warum wir explizite Transaktionen verwenden und überlegen, welche Schritte eine atomare Einheit bilden sollten der Arbeit.
Aber wenn Sie die tatsächlichen Arbeitseinheiten meinen , die in der expliziten Transaktion gruppiert werden, dann wissen Sie nicht, dass die Transaktion selbst ein Problem hatte. Sie wissen nur, dass eine Anweisung, die innerhalb der explizit definierten Transaktion ausgeführt wird, einen Fehler ausgelöst hat. Möglicherweise handelt es sich jedoch nicht um eine DML- oder DDL-Anweisung. Und selbst wenn es sich um eine DML-Anweisung handelt, kann die Transaktion selbst möglicherweise noch festgeschrieben werden.
In Anbetracht der beiden oben genannten Punkte sollten wir wahrscheinlich zwischen Transaktionen unterscheiden, die Sie nicht festschreiben können, und Transaktionen, die Sie nicht festschreiben möchten.
Wenn XACT_STATE()
a zurückgegeben 1
wird, bedeutet dies, dass die Transaktion "festschreibbar" ist und Sie die Wahl zwischen COMMIT
oder haben ROLLBACK
. Sie möchten es vielleicht nicht festschreiben, aber wenn Sie aus irgendeinem Grund, der schwer zu glätten ist, ein Beispiel haben möchten , könnten Sie es zumindest, weil einige Teile der Transaktion erfolgreich abgeschlossen wurden.
Aber wenn a XACT_STATE()
zurückkommt -1
, müssen Sie das wirklich tun, ROLLBACK
weil ein Teil der Transaktion in einen schlechten Zustand übergegangen ist. Nun stimme ich zu, dass, wenn die Steuerung an den CATCH-Block übergeben wurde, es sinnvoll genug ist, nur zu überprüfen @@TRANCOUNT
, denn selbst wenn Sie die Transaktion festschreiben könnten, warum sollten Sie das wollen?
Wenn Sie jedoch am oberen Rand des Beispiels feststellen, XACT_ABORT ON
ändert sich die Einstellung von ein wenig. Sie können einen regulären Fehler haben, danach BEGIN TRAN
wird die Steuerung an den CATCH-Block übergeben, wenn XACT_ABORT
ist OFF
und XACT_STATE () wird zurückkehren 1
. ABER wenn XACT_ABORT ist ON
, wird die Transaktion für jeden Fehler "abgebrochen" (dh ungültig gemacht) und XACT_STATE()
kehrt dann zurück -1
. In diesem Fall erscheint es sinnlos, XACT_STATE()
innerhalb des CATCH
Blocks zu prüfen , da er immer ein " -1
Wann XACT_ABORT
ist" zurückzugeben scheint ON
.
Also, wofür ist es dann XACT_STATE()
? Einige Hinweise sind:
Die MSDN-Seite für TRY...CATCH
im Abschnitt "Nicht festschreibbare Transaktionen und XACT_STATE" lautet:
Ein Fehler, der normalerweise eine Transaktion außerhalb eines TRY-Blocks beendet, führt dazu, dass eine Transaktion in einen nicht festschreibbaren Zustand wechselt, wenn der Fehler innerhalb eines TRY-Blocks auftritt.
Auf der MSDN-Seite für SET XACT_ABORT im Abschnitt "Hinweise" heißt es:
Wenn SET XACT_ABORT auf OFF gesetzt ist, wird in einigen Fällen nur die Transact-SQL-Anweisung zurückgesetzt, die den Fehler ausgelöst hat, und die Transaktion wird fortgesetzt.
und:
XACT_ABORT muss für Datenänderungsanweisungen in einer impliziten oder expliziten Transaktion für die meisten OLE DB-Anbieter, einschließlich SQL Server, auf ON gesetzt werden.
Auf der MSDN-Seite für BEGIN TRANSACTION im Abschnitt "Hinweise" heißt es:
Die von der BEGIN TRANSACTION-Anweisung gestartete lokale Transaktion wird in eine verteilte Transaktion eskaliert, wenn die folgenden Aktionen ausgeführt werden, bevor die Anweisung festgeschrieben oder zurückgesetzt wird:
- Eine INSERT-, DELETE- oder UPDATE-Anweisung, die auf eine Remotetabelle auf einem Verbindungsserver verweist, wird ausgeführt. Die INSERT-, UPDATE- oder DELETE-Anweisung schlägt fehl, wenn der OLE DB-Anbieter, der für den Zugriff auf den Verbindungsserver verwendet wird, die ITransactionJoin-Schnittstelle nicht unterstützt.
Die am besten geeignete Verwendung scheint im Kontext von DML-Anweisungen für Verbindungsserver zu liegen. Und ich glaube, ich bin selbst vor Jahren darauf gestoßen. Ich erinnere mich nicht an alle Details, aber es hatte etwas damit zu tun, dass der Remote-Server nicht verfügbar war, und aus irgendeinem Grund wurde dieser Fehler nicht im TRY-Block abgefangen und nie an den CATCH gesendet, und so geschah es ein COMMIT, wenn es nicht hätte sein sollen. Natürlich, das könnte hat ein Problem von nicht gewesen zu XACT_ABORT
Satz ON
anstatt Fehler zu überprüfen , XACT_STATE()
beide oder möglicherweise. Und ich erinnere mich, etwas gelesen zu haben, das besagt, wenn Sie Verbindungsserver und / oder verteilte Transaktionen verwenden, dann müssen Sie XACT_ABORT ON
und / oder verwenden XACT_STATE()
, aber ich kann das Dokument anscheinend jetzt nicht finden. Wenn ich es finde, werde ich dies mit dem Link aktualisieren.
Trotzdem habe ich einige Dinge ausprobiert und kann kein Szenario finden, das XACT_ABORT ON
die Kontrolle über den CATCH
Block mit der XACT_STATE()
Berichterstellung hat und an diesen übergibt 1
.
Probieren Sie diese Beispiele aus, um die Auswirkung von XACT_ABORT
auf den Wert von zu sehen XACT_STATE()
:
SET XACT_ABORT OFF;
BEGIN TRY
BEGIN TRAN;
SELECT 1/0 AS [DivideByZero]; -- error, yo!
COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK;
END;
END CATCH;
GO ------------------------------------------------
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRAN;
SELECT 1/0 AS [DivideByZero]; -- error, yo!
COMMIT TRAN;
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
IF (@@TRANCOUNT > 0)
BEGIN
ROLLBACK;
END;
END CATCH;
GO ------------------------------------------------
SET XACT_ABORT ON;
BEGIN TRY
SELECT 1/0 AS [DivideByZero]; -- error, yo!
END TRY
BEGIN CATCH
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
XACT_STATE() AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage]
END CATCH;
AKTUALISIEREN
Obwohl nicht Teil der ursprünglichen Frage, basierend auf diesen Kommentaren zu dieser Antwort:
Ich habe durch Erland Erzeugnisse auf Lesefehler und Transaktionsabwicklung , wo er sagt , dass XACT_ABORT
ist OFF
standardmäßig für Legacy - Gründe und normalerweise sollten wir es einstellen ON
.
...
"... wenn Sie der Empfehlung folgen und SET XACT_ABORT ON ausführen, ist die Transaktion immer zum Scheitern verurteilt."
Bevor XACT_ABORT ON
ich es überall verwende, würde ich fragen: Was genau wird hier gewonnen? Ich habe es nicht für notwendig befunden und befürworte generell, dass Sie es nur verwenden sollten, wenn es notwendig ist. Ob Sie ROLLBACK
mit der in @ Remus ' Antwort gezeigten Vorlage fertig werden möchten oder nicht , oder mit der Vorlage, die ich seit Jahren verwende, ist im Wesentlichen das Gleiche, jedoch ohne den in dieser Antwort gezeigten Speicherpunkt (welcher) behandelt verschachtelte Anrufe):
Müssen wir Transaktionen sowohl im C # -Code als auch in gespeicherten Prozeduren abwickeln?
UPDATE 2
Ich habe ein bisschen mehr getestet, diesmal indem ich eine kleine .NET-Konsolen-App erstellt habe, eine Transaktion in der App-Ebene erstellt habe, bevor ich SqlCommand
Objekte (dh über using (SqlTransaction _Tran = _Connection.BeginTransaction()) { ...
) ausgeführt habe, und statt einer Anweisung einen Batch-Abbruch-Fehler verwendet habe -aborting Fehler und stellte fest, dass:
- Eine "unverbindliche" Transaktion ist eine Transaktion, die größtenteils bereits zurückgesetzt wurde (die Änderungen wurden rückgängig gemacht), aber
@@TRANCOUNT
immer noch> 0 ist.
- Wenn Sie eine "nicht festschreibbare" Transaktion haben, können Sie keine ausstellen, da dies zu einer
COMMIT
Fehlermeldung führt, dass die Transaktion "nicht festschreibbar" ist. Sie können es auch nicht ignorieren / nichts tun, da ein Fehler generiert wird, wenn der Stapel beendet ist und besagt, dass der Stapel mit einer verweilenden, nicht festgeschriebenen Transaktion abgeschlossen wurde und zurückgesetzt wird (also, ähm, wenn er trotzdem automatisch zurückgesetzt wird, warum die Mühe machen, den Fehler zu werfen?). Sie müssen also einen expliziten ROLLBACK
Befehl ausgeben , möglicherweise nicht im unmittelbaren CATCH
Block, sondern bevor der Stapel endet.
- In einem
TRY...CATCH
Konstrukt, wenn XACT_ABORT
ist OFF
, Fehler , die die Transaktion beenden würden, wenn sie automatisch außerhalb eines aufgetreten TRY
Blockes, wie Batch-Abbruch Fehler, wird die Arbeit rückgängig gemacht werden, aber nicht die Tranasction beendet, wird es als „uncommitable“ zu verlassen. Die Ausgabe von a ROLLBACK
ist eher eine Formalität, die zum Abschluss der Transaktion erforderlich ist, aber die Arbeit wurde bereits zurückgesetzt.
- Wann
XACT_ABORT
ist ON
, wirken die meisten Fehler wie ein Batch-Abbruch und verhalten sich daher so, wie es in dem Punkt direkt oben (# 3) beschrieben ist.
XACT_STATE()
Zumindest in einem CATCH
Block wird ein -1
zum Batch-Abbrechen von Fehlern angezeigt, wenn zum Zeitpunkt des Fehlers eine Transaktion aktiv war.
XACT_STATE()
kehrt manchmal zurück, 1
auch wenn keine Transaktion aktiv ist. Wenn @@SPID
(unter anderem) in der SELECT
Liste mit enthalten ist XACT_STATE()
, XACT_STATE()
wird 1 zurückgegeben, wenn keine Transaktion aktiv ist. Dieses Verhalten hat in SQL Server 2012 begonnen und ist in 2014 vorhanden, aber ich habe es in 2016 nicht getestet.
Unter Berücksichtigung der obigen Punkte:
- Gegeben Punkte # 4 und # 5, da die meisten (oder alle?) Fehler eine Transaktion „uncommitable“ machen wird, so scheint es völlig sinnlos , zu überprüfen ,
XACT_STATE()
in dem CATCH
Block , wenn XACT_ABORT
ist , ON
da der Wert zurückgegeben wird es immer sein -1
.
- Überprüfung
XACT_STATE()
im CATCH
Block , wenn XACT_ABORT
ist OFF
mehr sinnvoll ist , da der Wert Rückkehr wird zumindest ein gewisse Variation hat , da es zurück 1
zum statement-Abbruch Fehler. Wenn Sie jedoch wie die meisten von uns codieren, ist diese Unterscheidung bedeutungslos, da Sie ROLLBACK
ohnehin nur deshalb anrufen , weil ein Fehler aufgetreten ist.
- Wenn Sie eine Situation , den Haftbefehl ausstellt , handelt eine
COMMIT
in dem CATCH
Block, dann überprüfen Sie den Wert XACT_STATE()
, und sicher sein , zu SET XACT_ABORT OFF;
.
XACT_ABORT ON
scheint wenig bis gar keinen Nutzen gegenüber dem TRY...CATCH
Konstrukt zu haben.
- Ich kann kein Szenario finden, in dem das Prüfen
XACT_STATE()
einen bedeutenden Vorteil gegenüber dem bloßen Prüfen bietet @@TRANCOUNT
.
- Ich kann auch kein Szenario , wo finden
XACT_STATE()
kehrt 1
in einem CATCH
Block , wenn XACT_ABORT
ist ON
. Ich denke, es ist ein Dokumentationsfehler.
- Ja, Sie können eine Transaktion, die Sie nicht explizit begonnen haben, rückgängig machen. Und im Zusammenhang mit der Verwendung
XACT_ABORT ON
ist dies ein strittiger Punkt, da ein in einem TRY
Block auftretender Fehler die Änderungen automatisch zurücksetzt.
- Das
TRY...CATCH
Konstrukt hat den Vorteil, XACT_ABORT ON
dass die gesamte Transaktion nicht automatisch abgebrochen wird und somit die Transaktion (solange sie XACT_STATE()
zurückgegeben wird 1
) festgeschrieben werden kann (auch wenn dies ein Edge-Case ist).
Beispiel für die XACT_STATE()
Rückkehr -1
wann XACT_ABORT
ist OFF
:
SET XACT_ABORT OFF;
BEGIN TRY
BEGIN TRAN;
SELECT CONVERT(INT, 'g') AS [ConversionError];
COMMIT TRAN;
END TRY
BEGIN CATCH
DECLARE @State INT;
SET @State = XACT_STATE();
SELECT @@TRANCOUNT AS [@@TRANCOUNT],
@State AS [XactState],
ERROR_MESSAGE() AS [ErrorMessage];
IF (@@TRANCOUNT > 0)
BEGIN
SELECT 'Rollin back...' AS [Transaction];
ROLLBACK;
END;
END CATCH;
UPDATE 3
Bezogen auf Artikel 6 in Abschnitt UPDATE 2 (dh möglicherweise falscher Wert, der zurückgegeben wird, XACT_STATE()
wenn keine Transaktion aktiv ist):
- Das seltsame / fehlerhafte Verhalten wurde in SQL Server 2012 gestartet (bisher mit 2012 SP2 und 2014 SP1 getestet)
- In den SQL Server-Versionen 2005, 2008 und 2008 R2 wurden
XACT_STATE()
bei Verwendung in Triggern oder INSERT...EXEC
Szenarien keine erwarteten Werte gemeldet : xact_state () kann nicht zuverlässig verwendet werden, um zu bestimmen, ob eine Transaktion zum Scheitern verurteilt ist . In diesen 3 Versionen (die ich nur auf 2008 R2 getestet habe) wird XACT_STATE()
jedoch nicht fälschlicherweise berichtet, 1
wenn sie in einem SELECT
mit verwendet werden @@SPID
.
Gegen das hier erwähnte Verhalten ist ein Connect-Fehler aufgetreten, der jedoch als "By Design" geschlossen wird: XACT_STATE () kann in SQL 2012 einen falschen Transaktionsstatus zurückgeben . Der Test wurde jedoch bei der Auswahl eines DMV durchgeführt und es wurde der Schluss gezogen, dass dies natürlich eine systemgenerierte Transaktion hätte, zumindest für einige DMVs. In der abschließenden Antwort der MS wurde außerdem Folgendes festgestellt:
Beachten Sie, dass eine IF-Anweisung und auch ein SELECT ohne FROM keine Transaktion starten.
Wenn Sie beispielsweise SELECT XACT_STATE () ausführen, wenn Sie keine zuvor vorhandene Transaktion haben, wird 0 zurückgegeben.
Diese Aussagen sind im folgenden Beispiel falsch:
SELECT @@TRANCOUNT AS [TRANCOUNT], XACT_STATE() AS [XACT_STATE], @@SPID AS [SPID];
GO
DECLARE @SPID INT;
SET @SPID = @@SPID;
SELECT @@TRANCOUNT AS [TRANCOUNT], XACT_STATE() AS [XACT_STATE], @SPID AS [SPID];
GO
Daher gibt der neue Connect-Fehler
XACT_STATE () 1 zurück, wenn er in SELECT mit einigen Systemvariablen, jedoch ohne FROM-Klausel verwendet wird
BITTE BEACHTEN SIE, dass in dem direkt darüber verknüpften Connect-Element "XACT_STATE () kann einen falschen Transaktionsstatus in SQL 2012 zurückgeben" Microsoft (nun, ein Vertreter von) Folgendes angibt:
@@ trancount gibt die Anzahl der BEGIN TRAN-Anweisungen zurück. Es ist daher kein verlässlicher Indikator dafür, ob eine Transaktion aktiv ist. XACT_STATE () gibt auch 1 zurück, wenn eine Autocommit-Transaktion aktiv ist, und ist daher ein zuverlässigerer Indikator dafür, ob eine Transaktion aktiv ist.
Ich kann jedoch keinen Grund finden, nicht zu vertrauen @@TRANCOUNT
. Der folgende Test zeigt, dass in einer Auto-Commit-Transaktion @@TRANCOUNT
tatsächlich Folgendes zurückgegeben 1
wird:
--- begin setup
GO
CREATE PROCEDURE #TransactionInfo AS
SET NOCOUNT ON;
SELECT @@TRANCOUNT AS [TranCount],
XACT_STATE() AS [XactState];
GO
--- end setup
DECLARE @Test TABLE (TranCount INT, XactState INT);
SELECT * FROM @Test; -- no rows
EXEC #TransactionInfo; -- 0 for both fields
INSERT INTO @Test (TranCount, XactState)
EXEC #TransactionInfo;
SELECT * FROM @Test; -- 1 row; 1 for both fields
Ich habe auch an einem realen Tisch mit einem Trigger getestet und @@TRANCOUNT
im Trigger genau berichtet 1
, obwohl keine explizite Transaktion gestartet wurde.
XACT_ABORT
aufON
oderOFF
.