TRY...CATCH (Transact-SQL)
Gilt für: SQL Server Azure SQL-Datenbank Azure SQL Managed Instance Azure Synapse Analytics Analytics Platform System (PDW) SQL Analytics-Endpunkt in Microsoft Fabric Warehouse in Microsoft Fabric
Implementiert die Fehlerbehandlung für Transact-SQL, die der Ausnahmebehandlung in den Sprachen C# und Visual C++ ähnelt. Eine Gruppe von Transact-SQL-Anweisungen kann in einen TRY
Block eingeschlossen werden. Wenn im Block ein Fehler auftritt, wird das Steuerelement in der TRY
Regel an eine andere Gruppe von Anweisungen übergeben, die in einen CATCH
Block eingeschlossen sind.
Transact-SQL-Syntaxkonventionen
Syntax
BEGIN TRY
{ sql_statement | statement_block }
END TRY
BEGIN CATCH
[ { sql_statement | statement_block } ]
END CATCH
[ ; ]
Argumente
sql_statement
Jede Transact-SQL-Anweisung.
statement_block
Jede Gruppe von Transact-SQL-Anweisungen in einem Batch oder in einen BEGIN...END
Block eingeschlossen.
Hinweise
Ein TRY...CATCH
Konstrukt erfasst alle Ausführungsfehler, die einen Schweregrad über 10 haben, der die Datenbankverbindung nicht schließt.
Auf TRY
einen Block muss sofort ein zugeordneter CATCH
Block folgen. Wenn Sie andere Anweisungen zwischen den END TRY
Anweisungen einschließen BEGIN CATCH
, wird ein Syntaxfehler generiert.
Ein TRY...CATCH
Konstrukt kann nicht mehrere Batches umfassen. Ein TRY...CATCH
Konstrukt kann nicht mehrere Blöcke von Transact-SQL-Anweisungen umfassen. Ein Konstrukt kann beispielsweise TRY...CATCH
keine zwei BEGIN...END
Blöcke von Transact-SQL-Anweisungen umfassen und kann kein Konstrukt umfassen IF...ELSE
.
Wenn kein Fehler im Code vorhanden ist, der in einen TRY
Block eingeschlossen ist, wird das Steuerelement nach Abschluss der letzten Anweisung im TRY
Block an die END CATCH
Anweisung übergeben.
Wenn im Code, der in einen TRY
Block eingeschlossen ist, ein Fehler auftritt, wird das Steuerelement an die erste Anweisung im zugeordneten CATCH
Block übergeben. Wenn der Code im CATCH
Block abgeschlossen ist, wird das Steuerelement unmittelbar nach der Anweisung an die END CATCH
Anweisung übergeben.
Hinweis
Wenn es sich bei der END CATCH
Anweisung um die letzte Anweisung in einer gespeicherten Prozedur oder einem Trigger handelt, wird das Steuerelement an die Anweisung übergeben, die die gespeicherte Prozedur aufgerufen oder den Trigger ausgelöst hat.
Fehler, die von einem CATCH
Block abgefangen werden, werden nicht an die aufrufende Anwendung zurückgegeben. Wenn ein Teil der Fehlerinformationen an die Anwendung zurückgegeben werden muss, muss der Code im CATCH
Block dies mithilfe von Mechanismen wie SELECT
Resultsets oder den RAISERROR
Anweisungen PRINT
tun.
TRY...CATCH
Konstrukte können geschachtelt werden. Ein TRY
Block oder ein CATCH
Block kann geschachtelte Konstrukte TRY...CATCH
enthalten. Ein Block kann z. B. ein eingebettetes TRY...CATCH
Konstrukt enthalten, um Fehler zu behandeln, CATCH
die CATCH
vom Code aufgetreten sind.
Fehler, die in einem CATCH
Block aufgetreten sind, werden wie Fehler behandelt, die an einer anderen Stelle generiert werden. Wenn der CATCH
Block ein geschachteltes TRY...CATCH
Konstrukt enthält, übergibt ein Fehler im geschachtelten TRY
Block das Steuerelement an den geschachtelten CATCH
Block. Wenn kein geschachteltes TRY...CATCH
Konstrukt vorhanden ist, wird der Fehler an den Aufrufer übergeben.
TRY...CATCH
erstellt unbehandelte Fehler aus gespeicherten Prozeduren oder Triggern, die vom Code im TRY
Block ausgeführt werden. Alternativ können die gespeicherten Prozeduren oder Trigger eigene TRY...CATCH
Konstrukte zum Behandeln von Fehlern enthalten, die durch ihren Code generiert werden. Wenn beispielsweise ein TRY
Block eine gespeicherte Prozedur ausführt und ein Fehler in der gespeicherten Prozedur auftritt, kann der Fehler wie folgt behandelt werden:
Wenn die gespeicherte Prozedur kein eigenes
TRY...CATCH
Konstrukt enthält, gibt der Fehler das Steuerelement an den Block zurück, derCATCH
dem Block zugeordnet ist, derTRY
dieEXECUTE
Anweisung enthält.Wenn die gespeicherte Prozedur ein
TRY...CATCH
Konstrukt enthält, überträgt das Fehlersteuerelement an denCATCH
Block in der gespeicherten Prozedur. Wenn derCATCH
Blockcode abgeschlossen ist, wird das Steuerelement unmittelbar nach derEXECUTE
Anweisung, die die gespeicherte Prozedur aufgerufen hat, an die Anweisung zurückgesendet.
GOTO
Anweisungen können nicht zum Eingeben oder TRY
CATCH
Blockieren verwendet werden. GOTO
Anweisungen können verwendet werden, um zu einer Beschriftung innerhalb desselben TRY
oder Blocks zu springen oder CATCH
einen TRY
Block zu CATCH
verlassen.
Das TRY...CATCH
Konstrukt kann nicht in einer benutzerdefinierten Funktion verwendet werden.
Abrufen von Fehlerinformationen
Im Bereich eines CATCH
Blocks können die folgenden Systemfunktionen verwendet werden, um Informationen zu dem Fehler abzurufen, der dazu führte, dass der CATCH
Block ausgeführt wurde:
Funktion | Beschreibung |
---|---|
ERROR_NUMBER | Gibt die Nummer des Fehlers zurück. |
ERROR_SEVERITY | Gibt den Schweregrad zurück. |
ERROR_STATE | Gibt die Fehlerstatusnummer zurück. |
ERROR_PROCEDURE | Gibt den Namen der gespeicherten Prozedur zurück oder löst den Fehler aus. |
ERROR_LINE | Gibt die Zeilennummer innerhalb der Routine zurück, die den Fehler verursacht hat. |
ERROR_MESSAGE | Gibt den vollständigen Text der Fehlermeldung zurück. Der Text umfasst die Werte, die für alle ersetzbaren Parameter angegeben werden, wie z. B. Längen, Objektnamen oder Zeitangaben. |
Diese Funktionen werden zurückgegeben NULL
, wenn sie außerhalb des Bereichs des CATCH
Blocks aufgerufen werden. Fehlerinformationen können mithilfe dieser Funktionen von überall innerhalb des CATCH
Blockbereichs abgerufen werden. Das folgende Skript zeigt beispielsweise eine gespeicherte Prozedur, die Fehlerbehandlungsfunktionen umfasst. Im CATCH
-Block eines TRY...CATCH
-Konstrukts wird die gespeicherte Prozedur aufgerufen, und Informationen zum Fehler werden zurückgegeben.
-- Verify that the stored procedure does not already exist.
IF OBJECT_ID('usp_GetErrorInfo', 'P') IS NOT NULL
DROP PROCEDURE usp_GetErrorInfo;
GO
-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
GO
BEGIN TRY
-- Generate divide-by-zero error.
SELECT 1 / 0;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
END CATCH;
Die ERROR_*
Funktionen funktionieren auch in einem CATCH
Block innerhalb einer nativ kompilierten gespeicherten Prozedur.
Fehler, die von einem TRY nicht betroffen sind... CATCH-Konstrukt
TRY...CATCH
Konstrukte führen nicht die folgenden Bedingungen durch:
Warnungen oder Informationsmeldungen mit einem Schweregrad von 10 oder niedriger.
Fehler mit einem Schweregrad von 20 oder höher, die dazu führen, dass die Verarbeitung des SQL Server-Datenbank-Engine-Tasks für die Sitzung beendet wird. Wenn ein Fehler auftritt, der den Schweregrad von 20 oder höher aufweist und die Datenbankverbindung nicht unterbrochen wird,
TRY...CATCH
wird der Fehler behandelt.Warnungen, z. B. Clientunterbrechungsanforderungen oder unterbrochene Clientverbindungen.
Wenn ein Systemadministrator die
KILL
Anweisung zum Beenden der Sitzung verwendet.
Die folgenden Arten von Fehlern werden nicht von einem CATCH
Block behandelt, wenn sie auf derselben Ausführungsebene wie das TRY...CATCH
Konstrukt auftreten:
Kompilierungsfehler, z. B. Syntaxfehler, die die Ausführung eines Batches verhindern.
Fehler, die bei der Neukompilierung auf Anweisungsebene auftreten, beispielsweise Fehler bei der Objektnamensauflösung, die aufgrund einer verzögerten Namensauflösung nach der Kompilierung auftreten.
Fehler bei der Auflösung von Objektnamen
Diese Fehler werden auf die Ebene zurückgegeben, auf der der Batch, die gespeicherte Prozedur oder der Trigger ausgeführt wurden.
Wenn während der Kompilierung oder der Neukompilierung auf Anweisungsebene auf niedrigerer Ausführungsebene (z. B. beim Ausführen sp_executesql
oder einer benutzerdefinierten gespeicherten Prozedur) innerhalb des TRY
Blocks ein Fehler auftritt, tritt der Fehler auf einer niedrigeren Ebene als das TRY...CATCH
Konstrukt auf und wird vom zugeordneten CATCH
Block behandelt.
Das folgende Beispiel zeigt, wie ein von einer SELECT
Anweisung generierter Fehler bei der Objektnamenauflösung nicht vom TRY...CATCH
Konstrukt abgefangen wird, aber vom CATCH
Block abgefangen wird, wenn dieselbe SELECT
Anweisung in einer gespeicherten Prozedur ausgeführt wird.
BEGIN TRY
-- Table does not exist; object name resolution
-- error not caught.
SELECT *
FROM NonexistentTable;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH
Der Fehler wird nicht abgefangen, und die Steuerung übergibt das TRY...CATCH
Konstrukt auf die nächste höhere Ebene.
Wenn Sie die SELECT
Anweisung in einer gespeicherten Prozedur ausführen, tritt der Fehler auf einer Ebene unter dem TRY
Block auf. Der Fehler wird vom TRY...CATCH
Konstrukt behandelt.
-- Verify that the stored procedure does not exist.
IF OBJECT_ID(N'usp_ExampleProc', N'P') IS NOT NULL
DROP PROCEDURE usp_ExampleProc;
GO
-- Create a stored procedure that will cause an
-- object resolution error.
CREATE PROCEDURE usp_ExampleProc
AS
SELECT *
FROM NonexistentTable;
GO
BEGIN TRY
EXECUTE usp_ExampleProc;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
Nicht ansetzbare Transaktionen und XACT_STATE
Wenn ein in einem TRY
Block generierter Fehler bewirkt, dass der Status der aktuellen Transaktion ungültig wird, wird die Transaktion als nichtmittbare Transaktion klassifiziert. Ein Fehler, der eine Transaktion außerhalb eines TRY
Blocks beendet, führt dazu, dass eine Transaktion einen nicht aussetzbaren Zustand eingibt, wenn der Fehler innerhalb eines TRY
Blocks auftritt. Eine nicht aussetzbare Transaktion kann nur Lesevorgänge oder eine ROLLBACK TRANSACTION
. Die Transaktion kann keine Transact-SQL-Anweisungen ausführen, die einen Schreibvorgang oder einen COMMIT TRANSACTION
. Die XACT_STATE
Funktion gibt einen Wert zurück, der -1
angibt, ob eine Transaktion als unkommittierbare Transaktion klassifiziert wurde. Nach Abschluss einer Batchausführung wird für alle aktiven nicht commitfähigen Transaktionen von Datenbank-Engine ein Rollback ausgeführt. Wenn keine Fehlermeldung gesendet wurde, wenn die Transaktion einen nicht aussetzbaren Zustand eingegeben hat, wird beim Abschluss des Batches eine Fehlermeldung an die Clientanwendung gesendet. Auf diese Weise wird angezeigt, dass eine nicht commitfähige Transaktion erkannt und ein Rollback für sie ausgeführt wurde.
Weitere Informationen zu nichtmittierbaren Transaktionen und der XACT_STATE
Funktion finden Sie unter XACT_STATE.
Beispiele
A. Verwenden von TRY... CATCH
Das folgende Beispiel zeigt eine SELECT
-Anweisung, die einen Fehler aufgrund einer Division durch 0 (null) generiert. Der Fehler führt dazu, dass die Ausführung zum dazugehörigen CATCH
-Block wechselt.
BEGIN TRY
-- Generate a divide-by-zero error.
SELECT 1 / 0;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
END CATCH;
GO
B. Verwenden Sie TRY... CATCH in einer Transaktion
Das folgende Beispiel zeigt die Funktionsweise eines TRY...CATCH
-Blocks innerhalb einer Transaktion. Die Anweisung innerhalb des TRY
-Blocks generiert einen Fehler aufgrund einer Einschränkungsverletzung.
BEGIN TRANSACTION;
BEGIN TRY
-- Generate a constraint violation error.
DELETE
FROM Production.Product
WHERE ProductID = 980;
END TRY
BEGIN CATCH
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_LINE() AS ErrorLine,
ERROR_MESSAGE() AS ErrorMessage;
IF @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH;
IF @@TRANCOUNT > 0
COMMIT TRANSACTION;
GO
C. Verwenden Sie TRY... CATCH mit XACT_STATE
Das folgende Beispiel zeigt, wie das TRY...CATCH
-Konstrukt zur Behandlung von Fehlern verwendet wird, die innerhalb einer Transaktion auftreten. Über die XACT_STATE
-Funktion wird bestimmt, ob für die Transaktion ein Commit oder ein Rollback ausgeführt werden soll. In diesem Beispiel hat SET XACT_ABORT
den Wert ON
. Dies bewirkt, dass die Transaktion nach dem Fehler aufgrund einer Einschränkungsverletzung nicht commitfähig ist.
-- Check to see whether this stored procedure exists.
IF OBJECT_ID(N'usp_GetErrorInfo', N'P') IS NOT NULL
DROP PROCEDURE usp_GetErrorInfo;
GO
-- Create procedure to retrieve error information.
CREATE PROCEDURE usp_GetErrorInfo
AS
SELECT ERROR_NUMBER() AS ErrorNumber,
ERROR_SEVERITY() AS ErrorSeverity,
ERROR_STATE() AS ErrorState,
ERROR_LINE() AS ErrorLine,
ERROR_PROCEDURE() AS ErrorProcedure,
ERROR_MESSAGE() AS ErrorMessage;
GO
-- SET XACT_ABORT ON will cause the transaction to be uncommittable
-- when the constraint violation occurs.
SET XACT_ABORT ON;
BEGIN TRY
BEGIN TRANSACTION;
-- A FOREIGN KEY constraint exists on this table. This
-- statement will generate a constraint violation error.
DELETE
FROM Production.Product
WHERE ProductID = 980;
-- If the DELETE statement succeeds, commit the transaction.
COMMIT TRANSACTION;
END TRY
BEGIN CATCH
-- Execute error retrieval routine.
EXECUTE usp_GetErrorInfo;
-- Test XACT_STATE:
-- If 1, the transaction is committable.
-- If -1, the transaction is uncommittable and should
-- be rolled back.
-- XACT_STATE = 0 means that there is no transaction and
-- a commit or rollback operation would generate an error.
-- Test whether the transaction is uncommittable.
IF (XACT_STATE()) = -1
BEGIN
PRINT N'The transaction is in an uncommittable state. Rolling back transaction.'
ROLLBACK TRANSACTION;
END;
-- Test whether the transaction is committable.
-- You may want to commit a transaction in a catch block if you want to commit changes to statements that ran prior to the error.
IF (XACT_STATE()) = 1
BEGIN
PRINT N'The transaction is committable. Committing transaction.'
COMMIT TRANSACTION;
END;
END CATCH;
GO
Zugehöriger Inhalt
- THROW (Transact-SQL)
- Datenbank-Engine Fehlerschweregrad
- ERROR_LINE (Transact-SQL)
- ERROR_MESSAGE (Transact-SQL)
- ERROR_NUMBER (Transact-SQL)
- ERROR_PROCEDURE (Transact-SQL)
- ERROR_SEVERITY (Transact-SQL)
- ERROR_STATE (Transact-SQL)
- RAISERROR (Transact-SQL)
- @@ERROR (Transact-SQL)
- GOTO (Transact-SQL)
- BEGIN...END (Transact-SQL)
- XACT_STATE (Transact-SQL)
- SET XACT_ABORT (Transact-SQL)