Megosztás a következőn keresztül:


MEGPRÓBÁL... FOGÁS (Transact-SQL)

A következőkre vonatkozik:SQL ServerAzure SQL DatabaseFelügyelt Azure SQL-példányAzure Synapse AnalyticsElemzési platformrendszer (PDW)SQL Analytics-végpont a Microsoft FabricbenRaktár a Microsoft FabricbenSQL-adatbázis a Microsoft Fabricben

A C# és a Visual C++ nyelv kivételkezeléséhez hasonló Transact-SQL hibakezelését valósítja meg. A blokkokban Transact-SQL utasítások egy csoportja is szerepelhet TRY . Ha hiba történik a blokkban, a TRY vezérlőt általában egy blokkba CATCH zárt utasításcsoportnak továbbítja a rendszer.

Transact-SQL szintaxis konvenciók

Syntax

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

Arguments

sql_statement

Bármilyen Transact-SQL utasítás.

statement_block

Egy kötegben vagy blokkban BEGIN...END lévő Transact-SQL utasítások bármely csoportja.

Remarks

A TRY...CATCH szerkezet minden olyan végrehajtási hibát elkap, amely 10-nél nagyobb súlyossággal rendelkezik, és nem zárja be az adatbázis-kapcsolatot.

A TRY blokkokat azonnal egy társított CATCH blokknak kell követnie. Az és az END TRYBEGIN CATCH utasítások közötti egyéb utasítások is szintaxishibát okoznak.

Egy TRY...CATCH szerkezet nem terjedhet ki több kötegre. A TRY...CATCH szerkezetek nem képesek Transact-SQL utasítások több blokkjára. Egy szerkezet például TRY...CATCH nem képes Transact-SQL utasítások két BEGIN...END blokkjára, és nem képes átfogni egy konstrukciót IF...ELSE .

Ha a blokkban TRY található kódban nincsenek hibák, amikor a blokk utolsó utasítása befejeződik, a TRY vezérlő közvetlenül a társított END CATCH utasítás után továbbítja az utasítást.

Ha a blokkba TRY zárt kódban hiba van, a vezérlő a társított CATCH blokk első utasítására kerül. Amikor a blokkban lévő kód befejeződik, a CATCH vezérlő közvetlenül az utasítás után továbbítja az utasítást END CATCH .

Note

Ha az END CATCH utasítás egy tárolt eljárás vagy eseményindító utolsó utasítása, a vezérlő visszakerül a tárolt eljárást meghívó vagy az eseményindítót aktiváló utasításra.

A blokk által CATCH csapdába esett hibák nem lesznek visszaadva a hívó alkalmazásnak. Ha a hibainformációk bármelyik részét vissza kell adni az alkalmazásnak, a CATCH blokk kódjának ezt olyan mechanizmusokkal kell megtennie, mint SELECT például az eredményhalmazok vagy a RAISERROR utasítások PRINT .

TRY...CATCH konstrukciók beágyazhatók. A TRY blokkok vagy blokkok CATCH beágyazott TRY...CATCH szerkezeteket tartalmazhatnak. A blokkok tartalmazhatnak például CATCH beágyazott TRY...CATCH szerkezetet a CATCH kód által észlelt hibák kezelésére.

A blokkokban CATCH előforduló hibákat a rendszer máshol létrehozott hibákként kezeli. Ha a CATCH blokk beágyazott TRY...CATCH szerkezetet tartalmaz, a beágyazott TRY blokk esetleges hibája átadja a vezérlőt a beágyazott CATCH blokknak. Ha nincs beágyazott TRY...CATCH szerkezet, a hiba vissza lesz adva a hívónak.

TRY...CATCH a blokkban TRY lévő kód által végrehajtott tárolt eljárások vagy triggerek nem kezelt hibáit rögzíti. Másik lehetőségként a tárolt eljárások vagy eseményindítók saját TRY...CATCH szerkezeteket is tartalmazhatnak a kódjuk által generált hibák kezelésére. Ha például egy TRY blokk végrehajt egy tárolt eljárást, és hiba történik a tárolt eljárásban, a hiba a következő módokon kezelhető:

  • Ha a tárolt eljárás nem tartalmazza a saját TRY...CATCH szerkezetét, a hiba a vezérlőt adja vissza az CATCH utasítást tartalmazó TRY blokkhoz EXECUTE társított blokknak.

  • Ha a tárolt eljárás szerkezetet TRY...CATCH tartalmaz, a hiba átviszi a vezérlőt a CATCH blokkba a tárolt eljárásban. Amikor a CATCH blokkkód befejeződik, a rendszer a vezérlőt közvetlenül a tárolt eljárást meghívó utasítás után adja vissza az EXECUTE utasításnak.

GOTOutasításokkal nem lehet beírni egy vagy TRY több blokkotCATCH. GOTO utasításokkal egy címkére ugorhat ugyanazon TRY vagy CATCH blokkon belül, vagy elhagyhat egy TRY vagy CATCH több blokkot.

A TRY...CATCH szerkezet nem használható felhasználó által definiált függvényekben.

Hibainformációk lekérése

A blokk hatókörében CATCH a következő rendszerfüggvények használhatók a blokk végrehajtását okozó CATCH hibával kapcsolatos információk lekérésére:

Function Description
ERROR_NUMBER A hiba számát adja eredményül.
ERROR_SEVERITY A súlyosságot adja vissza.
ERROR_STATE A hibaállapot számát adja eredményül.
ERROR_PROCEDURE Annak a tárolt eljárásnak vagy eseményindítónak a nevét adja vissza, ahol a hiba történt.
ERROR_LINE A hibát okozó rutinon belüli sorszámot adja vissza.
ERROR_MESSAGE A hibaüzenet teljes szövegét adja vissza. A szöveg tartalmazza a helyettesíthető paraméterekhez megadott értékeket, például a hosszokat, az objektumneveket vagy az időpontokat.

Ezek a függvények akkor térnek vissza NULL , ha a blokk hatókörén CATCH kívül vannak meghívva. A hibainformációk a blokk hatókörének CATCH bármely pontjáról lekérhetők ezen függvények használatával. Az alábbi szkript például egy tárolt eljárást mutat be, amely hibakezelési függvényeket tartalmaz. CATCH A szerkezet blokkjában TRY...CATCH a rendszer meghívja a tárolt eljárást, és visszaadja a hibával kapcsolatos információkat.

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

A ERROR_* függvények egy CATCHnatívan lefordított tárolt eljárás blokkjában is működnek.

A TRY által nem észlelt hibák... CATCH szerkezet

TRY...CATCH a szerkezetek nem csapják le a következő feltételeket:

  • 10 vagy annál kisebb súlyosságú figyelmeztetések vagy tájékoztató üzenetek.

  • 20 vagy annál nagyobb súlyosságú hibák, amelyek leállják az SQL Server adatbázismotorjának feladatfeldolgozását a munkamenethez. Ha olyan hiba történik, amely 20 vagy annál nagyobb súlyossággal rendelkezik, és az adatbázis-kapcsolat nem szakad meg, TRY...CATCH kezeli a hibát.

  • Figyelemfelhívások, például ügyfél-megszakítási kérések vagy megszakadt ügyfélkapcsolatok.

  • Amikor egy rendszergazda az KILL utasítást használja a munkamenet befejezéséhez.

A következő típusú hibákat a blokkok nem kezelik CATCH , ha azok a szerkezettel azonos végrehajtási TRY...CATCH szinten fordulnak elő:

  • Fordítási hibák, például szintaxishibák, amelyek megakadályozzák a köteg futását.

  • Az utasításszintű újrafordítás során fellépő hibák, például az objektumok névfeloldási hibái, amelyek a halasztott névfeloldás miatt a fordítás után következnek be.

  • Objektumnévfeloldási hibák

Ezek a hibák a köteg, a tárolt eljárás vagy az eseményindító futtatásának szintjére kerülnek vissza.

Ha a fordítás vagy az utasításszintű újrafordítás során hiba történik alacsonyabb végrehajtási szinten (például végrehajtáskor sp_executesql vagy felhasználó által definiált tárolt eljárás esetén), TRY a hiba a szerkezetnél TRY...CATCH alacsonyabb szinten jelentkezik, és a társított CATCH blokk fogja kezelni.

Az alábbi példa bemutatja, hogy egy SELECT utasítás által generált objektumnévfeloldási hibát nem a szerkezet észleli TRY...CATCH , hanem a CATCH blokk észleli, amikor ugyanazt SELECT az utasítást egy tárolt eljárásban hajtja végre.

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

A hiba nem jelenik meg, és a TRY...CATCH vezérlés a következő magasabb szintre kerül.

Ha egy tárolt eljárásban futtatja az SELECT utasítást, a hiba a blokknál TRY alacsonyabb szinten jelentkezik. A hibát a TRY...CATCH szerkezet kezeli.

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

Nem véglegesíthető tranzakciók és XACT_STATE

Ha egy TRY blokkban generált hiba az aktuális tranzakció állapotát érvényteleníti, a tranzakció nem véglegesített tranzakcióként lesz besorolva. Egy olyan hiba, amely általában egy blokkon kívüli TRY tranzakciót végződik, a tranzakció nem egyeztethető állapotba kerül, amikor a hiba egy TRY blokkon belül történik. A nem véglegesített tranzakciók csak olvasási műveleteket vagy egy ROLLBACK TRANSACTION. A tranzakció nem tud olyan Transact-SQL utasítást végrehajtani, amely írási műveletet vagy COMMIT TRANSACTIONegy . A XACT_STATE függvény annak értékét -1 adja vissza, ha egy tranzakciót nem véglegesített tranzakcióként soroltak be. Amikor egy köteg befejeződik, az adatbázismotor visszaállítja az aktív, nem véglegesíthető tranzakciókat. Ha a tranzakció nem véglegesített állapotba helyezésekor nem érkezett hibaüzenet, a köteg befejeződésekor a rendszer hibaüzenetet küld az ügyfélalkalmazásnak. Ez azt jelzi, hogy a rendszer nem véglegesített tranzakciót észlelt és visszaállított.

További információ a nem véglegesíthető tranzakciókról és a XACT_STATE függvényről: XACT_STATE.

Examples

A. A TRY használata... ELKAP

Az alábbi példa egy olyan utasítást SELECT mutat be, amely osztva nullával hibát okoz. A hiba miatt a végrehajtás a társított CATCH blokkra ugrik.

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. A TRY használata... CATCH egy tranzakcióban

Az alábbi példa bemutatja, hogyan működik egy TRY...CATCH blokk egy tranzakción belül. A blokkon belüli TRY utasítás kényszermegsértési hibát okoz.

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. A TRY használata... CATCH és XACT_STATE

Az alábbi példa bemutatja, hogyan kezelhetők a tranzakción belül előforduló hibák a TRY...CATCH szerkezettel. A XACT_STATE függvény meghatározza, hogy a tranzakciót le kell-e véglegesíteni vagy vissza kell-e állítani. Ebben a példában SET XACT_ABORT a következő: ON. Így a tranzakció nem lesz véglegesíthető, ha a korlátozásmegsértési hiba bekövetkezik.

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