Udostępnij za pomocą


PRÓBOWAĆ... CATCH (Transact-SQL)

Dotyczy:SQL ServerAzure SQL DatabaseAzure SQL Managed InstanceAzure Synapse AnalyticsAnalytics Platform System (PDW)Punkt końcowy analizy SQL w usłudze Microsoft FabricHurtownia danych w usłudze Microsoft FabricBaza danych SQL w usłudze Microsoft Fabric

Implementuje obsługę błędów dla Transact-SQL, które są podobne do obsługi wyjątków w językach C# i Visual C++. Grupę instrukcji Transact-SQL można ujęć w TRY blok. Jeśli w TRY bloku wystąpi błąd, kontrolka jest zwykle przekazywana do innej grupy instrukcji, które są ujęte w CATCH bloku.

Transact-SQL konwencje składni

Syntax

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

Arguments

sql_statement

Dowolna instrukcja Transact-SQL.

statement_block

Każda grupa instrukcji Transact-SQL w partii lub ujęta w BEGIN...END blok.

Remarks

Konstrukcja TRY...CATCH przechwytuje wszystkie błędy wykonywania o ważności większej niż 10, które nie zamykają połączenia z bazą danych.

Blok TRY musi być natychmiast obserwowany przez skojarzony CATCH blok. Dołączenie innych instrukcji między instrukcjami END TRY i BEGIN CATCH powoduje wygenerowanie błędu składniowego.

Konstrukcja TRY...CATCH nie może obejmować wielu partii. Konstrukcja TRY...CATCH nie może obejmować wielu bloków instrukcji Transact-SQL. Na przykład TRY...CATCH konstrukcja nie może obejmować dwóch BEGIN...END bloków instrukcji Transact-SQL i nie może obejmować IF...ELSE konstrukcji.

Jeśli w kodzie, który znajduje się w TRY bloku, nie ma żadnych błędów, po zakończeniu TRY ostatniej instrukcji w bloku kontrolka przechodzi do instrukcji bezpośrednio po skojarzonej END CATCH instrukcji.

Jeśli w kodzie, który znajduje się w TRY bloku, występuje błąd, kontrolka przechodzi do pierwszej instrukcji w skojarzonym CATCH bloku. Po zakończeniu CATCH kodu w bloku kontrolka przechodzi do instrukcji bezpośrednio po instrukcji END CATCH .

Note

END CATCH Jeśli instrukcja jest ostatnią instrukcją w procedurze składowanej lub wyzwalaczu, kontrolka jest przekazywana z powrotem do instrukcji, która wywołała procedurę składowaną lub wyzwoliła wyzwalacz.

Błędy uwięzione przez CATCH blok nie są zwracane do aplikacji wywołującej. Jeśli jakakolwiek część informacji o błędzie musi zostać zwrócona do aplikacji, kod w CATCH bloku musi to zrobić przy użyciu mechanizmów, takich jak SELECT zestawy wyników lub RAISERROR instrukcje i PRINT .

TRY...CATCH konstrukcje można zagnieżdżać. TRY Blok lub CATCH blok może zawierać konstrukcje zagnieżdżoneTRY...CATCH. Na przykład CATCH blok może zawierać konstrukcję osadzoną TRY...CATCH do obsługi błędów napotkanych przez CATCH kod.

Błędy napotkane w bloku są traktowane jak błędy generowane w CATCH dowolnym miejscu. CATCH Jeśli blok zawiera konstrukcję zagnieżdżonąTRY...CATCH, każdy błąd w zagnieżdżonym TRY bloku przekazuje kontrolę do zagnieżdżonego CATCH bloku. Jeśli nie ma konstrukcji zagnieżdżonej TRY...CATCH , błąd zostanie przekazany z powrotem do elementu wywołującego.

TRY...CATCH konstrukcje przechwytują nieobsługiwane błędy z procedur składowanych lub wyzwalaczy wykonywanych przez kod w TRY bloku. Alternatywnie procedury składowane lub wyzwalacze mogą zawierać własne TRY...CATCH konstrukcje do obsługi błędów generowanych przez ich kod. Na przykład gdy TRY blok wykonuje procedurę składowaną i występuje błąd w procedurze składowanej, błąd można obsłużyć w następujący sposób:

  • Jeśli procedura składowana nie zawiera własnej TRY...CATCH konstrukcji, błąd zwraca kontrolkę do CATCH bloku skojarzonego TRY z blokiem zawierającym instrukcję EXECUTE .

  • Jeśli procedura składowana zawiera konstrukcję TRY...CATCH , błąd przenosi kontrolkę do CATCH bloku w procedurze składowanej. Po zakończeniu kodu bloku kontrolka CATCH jest przekazywana z powrotem do instrukcji bezpośrednio po EXECUTE instrukcji, która nazwała procedurę składowaną.

GOTO instrukcji nie można używać do wprowadzania instrukcji TRY lub CATCH . GOTO instrukcje mogą służyć do przechodzenia do etykiety wewnątrz tego samego TRY lub CATCH bloku lub do pozostawienia TRY lub CATCH bloku.

Konstrukcji TRY...CATCH nie można używać w funkcji zdefiniowanej przez użytkownika.

Pobieranie informacji o błędzie

W zakresie CATCH bloku następujące funkcje systemowe mogą służyć do uzyskiwania informacji o błędzie, który spowodował CATCH wykonanie bloku:

Function Description
ERROR_NUMBER Zwraca liczbę błędu.
ERROR_SEVERITY Zwraca ważność.
ERROR_STATE Zwraca numer stanu błędu.
ERROR_PROCEDURE Zwraca nazwę procedury składowanej lub wyzwalacza, w którym wystąpił błąd.
ERROR_LINE Zwraca numer wiersza wewnątrz procedury, która spowodowała błąd.
ERROR_MESSAGE Zwraca pełny tekst komunikatu o błędzie. Tekst zawiera wartości podane dla wszystkich parametrów podstawialnych, takich jak długość, nazwy obiektów lub godziny.

Te funkcje są zwracane NULL , jeśli są wywoływane poza zakresem CATCH bloku. Informacje o błędzie można pobrać przy użyciu tych funkcji z dowolnego miejsca w zakresie CATCH bloku. Na przykład poniższy skrypt przedstawia procedurę składowaną zawierającą funkcje obsługi błędów. CATCH W bloku TRY...CATCH konstrukcji wywoływana jest procedura składowana i zwracane są informacje o błędzie.

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

Funkcje ERROR_* działają również w CATCH bloku wewnątrz natywnie skompilowanej procedury składowanej.

Błędy, których nie dotyczy próba... Catch

TRY...CATCH konstrukcje nie wychwytują następujących warunków:

  • Ostrzeżenia lub komunikaty informacyjne, które mają ważność 10 lub niższą.

  • Błędy o ważności 20 lub wyższej, które zatrzymują przetwarzanie zadania aparatu bazy danych programu SQL Server dla sesji. Jeśli wystąpi błąd o ważności 20 lub wyższej, a połączenie z bazą danych nie zostanie przerwane, TRY...CATCH obsłuży błąd.

  • Uwagi, takie jak żądania przerwania klienta lub przerwane połączenia klienta.

  • Gdy administrator systemu używa instrukcji KILL , aby zakończyć sesję.

Następujące typy błędów nie są obsługiwane przez CATCH blok, gdy występują na tym samym poziomie wykonywania co TRY...CATCH konstrukcja:

  • Skompiluj błędy, takie jak błędy składni, które uniemożliwiają uruchomienie partii.

  • Błędy występujące podczas ponownej kompilacji na poziomie instrukcji, takie jak błędy rozpoznawania nazw obiektów występujące po kompilacji z powodu odroczonego rozpoznawania nazw.

  • Błędy rozpoznawania nazw obiektów

Te błędy są zwracane do poziomu, na poziomie, na który uruchomiono partię, procedurę składowaną lub wyzwalacz.

Jeśli podczas kompilacji lub ponownej kompilacji na poziomie instrukcji wystąpi błąd na niższym poziomie wykonywania (na przykład podczas wykonywania sp_executesql lub procedury składowanej zdefiniowanej przez użytkownika) wewnątrz TRY bloku, błąd występuje na niższym poziomie niż TRY...CATCH konstrukcja i będzie obsługiwany przez skojarzony CATCH blok.

W poniższym przykładzie pokazano, jak błąd rozpoznawania nazw obiektów generowany przez instrukcję SELECT nie jest przechwytywane przez TRY...CATCH konstrukcję, ale jest przechwycony przez CATCH blok, gdy ta sama SELECT instrukcja jest wykonywana wewnątrz procedury składowanej.

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

Błąd nie jest przechwycony, a kontrola przechodzi z TRY...CATCH konstrukcji do następnego wyższego poziomu.

Uruchomienie instrukcji SELECT wewnątrz procedury składowanej powoduje wystąpienie błędu na poziomie niższym niż TRY blok. Błąd jest obsługiwany przez konstrukcję 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;

Niezatwierdzonych transakcji i XACT_STATE

Jeśli błąd wygenerowany w TRY bloku powoduje unieważnienie stanu bieżącej transakcji, transakcja jest klasyfikowana jako transakcja nietwierdzona. Błąd, który zwykle kończy transakcję poza blokiem TRY , powoduje, że transakcja wprowadza stan niezatwierdzony, gdy błąd występuje wewnątrz TRY bloku. Transakcja nieutwierdzonych może wykonywać tylko operacje odczytu lub ROLLBACK TRANSACTION. Transakcja nie może wykonać żadnych instrukcji Transact-SQL, które generują operację zapisu lub COMMIT TRANSACTION. Funkcja XACT_STATE zwraca wartość -1 , jeśli transakcja została sklasyfikowana jako transakcja nieupowierzytna. Po zakończeniu wsadu aparat bazy danych wycofa wszystkie aktywne niezatwierdzonych transakcji. Jeśli żaden komunikat o błędzie nie został wysłany, gdy transakcja została wprowadzona w stanie niezatwierdzonych, po zakończeniu wsadu do aplikacji klienckiej zostanie wysłany komunikat o błędzie. Oznacza to, że wykryto niezatwierdzonej transakcji i wycofano.

Aby uzyskać więcej informacji na temat niezatwierdzonych transakcji i XACT_STATE funkcji, zobacz XACT_STATE.

Examples

A. Użyj funkcji TRY... ŁAPAĆ

W poniższym przykładzie pokazano instrukcję SELECT , która generuje błąd dzielenia przez zero. Błąd powoduje przejście wykonywania do skojarzonego CATCH bloku.

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. Użyj funkcji TRY... CATCH w transakcji

W poniższym przykładzie pokazano, jak TRY...CATCH blok działa wewnątrz transakcji. Instrukcja wewnątrz TRY bloku generuje błąd naruszenia ograniczeń.

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. Użyj funkcji TRY... CATCH z XACT_STATE

W poniższym przykładzie pokazano, jak za pomocą TRY...CATCH konstrukcji obsługiwać błędy występujące wewnątrz transakcji. Funkcja XACT_STATE określa, czy transakcja powinna zostać zatwierdzona, czy wycofana. W tym przykładzie SET XACT_ABORT jest ON. Powoduje to, że transakcja nie jest zatwierdzana, gdy wystąpi błąd naruszenia ograniczenia.

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