Sdílet prostřednictvím


ZKUSIT... CATCH (Transact-SQL)

Platí pro:SQL ServerAzure SQL DatabaseSpravovaná instance Azure SQLAzure Synapse AnalyticsAnalytics Platform System (PDW)Koncový bod analýzy SQL v Microsoft FabricSklad v Microsoft FabricDatabáze SQL v Microsoft Fabric

Implementuje zpracování chyb pro Transact-SQL, které se podobá zpracování výjimek v jazycích C# a Visual C++. Skupinu příkazů Transact-SQL lze uzavřít do TRY bloku. Pokud dojde k chybě v TRY bloku, ovládací prvek se obvykle předává jiné skupině příkazů, které jsou uzavřeny v CATCH bloku.

Transact-SQL konvence syntaxe

Syntax

BEGIN TRY
    { sql_statement | statement_block }
END TRY
BEGIN CATCH
    [ { sql_statement | statement_block } ]
END CATCH
[ ; ]

Arguments

sql_statement

Libovolný příkaz Transact-SQL.

statement_block

Libovolná skupina Transact-SQL příkazů v dávce nebo uzavřená v BEGIN...END bloku.

Remarks

Konstruktor TRY...CATCH zachytí všechny chyby spuštění, které mají závažnost vyšší než 10, které nezavírají připojení k databázi.

Blok TRY musí být okamžitě následovaný přidruženým CATCH blokem. Zahrnutí všech dalších příkazů mezi END TRY příkazy a BEGIN CATCH vygeneruje chybu syntaxe.

Konstruktor TRY...CATCH nemůže zahrnovat více dávek. Konstruktor TRY...CATCH nemůže zahrnovat více bloků příkazů Transact-SQL. Konstruktor nemůže například TRY...CATCH zahrnovat dva BEGIN...END bloky příkazů Transact-SQL a nemůže zahrnovat IF...ELSE konstruktor.

Pokud v kódu, který je uzavřen v TRY bloku, nejsou žádné chyby, když se dokončí poslední příkaz v TRY bloku, ovládací prvek předá příkaz bezprostředně za přidruženým END CATCH příkazem.

Pokud v kódu, který je uzavřený v TRY bloku, dojde k chybě, předá ovládací prvek první příkaz v přidruženém CATCH bloku. Jakmile se kód v CATCH bloku dokončí, ovládací prvek předá příkaz bezprostředně za END CATCH příkazem.

Note

END CATCH Pokud je příkaz posledním příkazem uložené procedury nebo triggeru, předá se ovládací prvek zpět do příkazu, který volal uloženou proceduru nebo aktivoval trigger.

Chyby zachycené blokem CATCH se nevracejí do volající aplikace. Pokud se do aplikace musí vrátit nějaká část informací o chybě, kód v CATCH bloku to musí provést pomocí mechanismů, jako SELECT jsou sady výsledků nebo RAISERROR příkazy a PRINT příkazy.

TRY...CATCH konstruktorů lze vnořit. TRY Blok nebo CATCH blok mohou obsahovat vnořené TRY...CATCH konstrukce. Blok může například obsahovat vložený konstruktor pro CATCH zpracování chyb zjištěných kódemTRY...CATCH.CATCH

Chyby, ke kterým došlo v CATCH bloku, se považují za chyby vygenerované kdekoli jinde. CATCH Pokud blok obsahuje vnořený TRY...CATCH konstruktor, všechny chyby v vnořeném TRY bloku předá řízení do vnořeného CATCH bloku. Pokud neexistuje žádný vnořený TRY...CATCH konstruktor, chyba se předá zpět volajícímu.

TRY...CATCH konstruktory zachytí neošetřené chyby z uložených procedur nebo triggerů spouštěných kódem v TRY bloku. Uložené procedury nebo triggery mohou také obsahovat vlastní TRY...CATCH konstrukce pro zpracování chyb generovaných jejich kódem. Pokud například TRY blok spustí uloženou proceduru a v uložené proceduře dojde k chybě, lze tuto chybu zpracovat následujícími způsoby:

  • Pokud uložená procedura neobsahuje vlastní TRY...CATCH konstruktor, vrátí chyba řízení bloku CATCH přidruženému TRY k bloku, který obsahuje EXECUTE příkaz.

  • Pokud uložená TRY...CATCH procedura obsahuje konstruktor, chyba přenese řízení do CATCH bloku uložené procedury. Jakmile se blokový CATCH kód dokončí, ovládací prvek se předá zpět do příkazu bezprostředně za EXECUTE příkazem, který volal uloženou proceduru.

GOTO příkazy nelze použít k zadání TRY nebo CATCH bloku. GOTO Příkazy lze použít k přeskakování na popisek uvnitř stejného TRY nebo CATCH bloku nebo k opuštění TRY nebo CATCH bloku.

Konstruktor TRY...CATCH nelze použít v uživatelem definované funkci.

Načtení informací o chybě

V oboru CATCH bloku lze použít následující systémové funkce k získání informací o chybě, která způsobila CATCH spuštění bloku:

Function Description
ERROR_NUMBER Vrátí číslo chyby.
ERROR_SEVERITY Vrátí závažnost.
ERROR_STATE Vrátí číslo chybového stavu.
ERROR_PROCEDURE Vrátí název uložené procedury nebo triggeru, kde došlo k chybě.
ERROR_LINE Vrátí číslo řádku uvnitř rutiny, která způsobila chybu.
ERROR_MESSAGE Vrátí úplný text chybové zprávy. Text obsahuje hodnoty zadané pro všechny parametry, jako jsou délky, názvy objektů nebo časy.

Tyto funkce se vrátí NULL , pokud se volají mimo rozsah CATCH bloku. Informace o chybách je možné načíst pomocí těchto funkcí odkudkoli v rozsahu CATCH bloku. Například následující skript ukazuje uloženou proceduru, která obsahuje funkce zpracování chyb. CATCH V bloku konstruktoru TRY...CATCH se volá uložená procedura a vrátí se informace o chybě.

-- 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;

Funkce ERROR_* také pracují v CATCH bloku uvnitř nativně zkompilované uložené procedury.

Chyby, které nejsou ovlivněny pokusem... Konstruktor CATCH

TRY...CATCH konstruktorů neschytí následující podmínky:

  • Upozornění nebo informační zprávy, které mají závažnost 10 nebo nižší.

  • Chyby, které mají závažnost 20 nebo vyšší, které zastaví zpracování úloh databázového stroje SQL Serveru pro relaci. Pokud dojde k chybě se závažností 20 nebo vyšší a připojení k databázi se nenaruší, TRY...CATCH zpracuje chybu.

  • Upozornění, jako jsou žádosti o přerušení klienta nebo přerušená připojení klientů.

  • Když správce systému použije příkaz KILL k ukončení relace.

Následující typy chyb nejsou zpracovávány blokem CATCH , pokud k nim dochází na stejné úrovni provádění jako konstruktor TRY...CATCH :

  • Chyby kompilace, například chyby syntaxe, které brání spuštění dávky.

  • Chyby, ke kterým dochází během rekompilace na úrovni příkazu, například chyby překladu názvů objektů, ke kterým dochází po kompilaci kvůli odložené překladu ip adres.

  • Chyby překladu názvů objektů

Tyto chyby se vrátí na úroveň, která spustila dávku, uloženou proceduru nebo trigger.

Pokud během kompilace nebo rekompilace na úrovni příkazu dojde k chybě na nižší úrovni spuštění (například při provádění sp_executesql nebo uživatelem definované uložené procedury) uvnitř TRY bloku, dojde k chybě na nižší úrovni než TRY...CATCH konstruktor a bude zpracován přidruženým CATCH blokem.

Následující příklad ukazuje, jak chyba překladu názvů objektu vygenerovaná příkazem SELECT není zachycena TRY...CATCH konstruktorem, ale je zachycena CATCH blokem při spuštění stejného SELECT příkazu uvnitř uložené procedury.

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

Chyba se nezachytí a ovládací prvek předá konstruktoru TRY...CATCH na další vyšší úroveň.

Spuštění příkazu SELECT uvnitř uložené procedury způsobí, že k chybě dojde na úrovni nižší než blok TRY . Chyba je zpracována konstruktorem TRY...CATCH .

-- 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;

Nezávazné transakce a XACT_STATE

Pokud chyba generovaná v TRY bloku způsobí zneplatnění stavu aktuální transakce, transakce je klasifikována jako nekommitovatelná transakce. Chyba, která obvykle ukončí transakci mimo TRY blok, způsobí, že transakce zadá nekommitovatelný stav, když dojde k chybě uvnitř TRY bloku. Nekommitovatelná transakce může provádět pouze operace čtení nebo operace ROLLBACK TRANSACTION. Transakce nemůže provést žádné Transact-SQL příkazy, které by vygenerovaly operaci zápisu nebo COMMIT TRANSACTION. Funkce XACT_STATE vrátí hodnotu -1 , pokud byla transakce klasifikována jako nekommitovatelná transakce. Po dokončení dávky databázový stroj vrátí zpět všechny aktivní nekommitovatelné transakce. Pokud nebyla odeslána žádná chybová zpráva, když transakce zadala nekommitovatelný stav, po dokončení dávky se do klientské aplikace odešle chybová zpráva. To znamená, že byla zjištěna a vrácena zpět nekommitovatelná transakce.

Další informace o uncommittable transactions and the XACT_STATE function, see XACT_STATE.

Examples

A. Použít try... CHYTIT

Následující příklad ukazuje SELECT příkaz, který generuje chybu dělení nulou. Tato chyba způsobí, že spuštění přeskočí na přidružený CATCH blok.

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. Použít try... CATCH v transakci

Následující příklad ukazuje, jak TRY...CATCH blok funguje uvnitř transakce. Příkaz uvnitř TRY bloku vygeneruje chybu porušení omezení.

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. Použít try... CATCH s XACT_STATE

Následující příklad ukazuje, jak pomocí konstruktoru TRY...CATCH zpracovat chyby, ke kterým dochází uvnitř transakce. Funkce XACT_STATE určuje, zda má být transakce potvrzena nebo vrácena zpět. V tomto příkladu SET XACT_ABORT je ON. To způsobí, že transakce nenícommittable, když dojde k chybě porušení omezení.

-- 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