TRY...CATCH (Transact-SQL)

Si applica a:yes SQL Server (tutte le versioni supportate) database SQL di Azure Istanza gestita di SQL di Azure YesyesAzure Synapse Analytics Analytics yesPlatform System (PDW) Yes

Implementa la gestione degli errori per Transact-SQL simile alla gestione delle eccezioni nei linguaggi Microsoft Visual C# e Microsoft Visual C++. Un gruppo di istruzioni Transact-SQL può essere racchiuso in un blocco TRY. Se si verifica un errore nel blocco TRY, il controllo viene passato a un altro gruppo di istruzioni racchiuso in un blocco CATCH.

Topic link iconConvenzioni di sintassi Transact-SQL

Sintassi

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

Nota

Per visualizzare la sintassi Transact-SQL per SQL Server 2014 e versioni precedenti, vedere Documentazione delle versioni precedenti.

Argomenti

sql_statement
Qualsiasi istruzione Transact-SQL.

statement_block
Qualsiasi gruppo di istruzioni Transact-SQL in un batch o racchiuso in un begin... Blocco END.

Osservazioni

Un costrutto TRY...CATCH intercetta tutti gli errori di esecuzione con livello di gravità superiore a 10 che non determinano la chiusura della connessione al database.

Un blocco TRY deve essere immediatamente seguito da un blocco CATCH associato. L'inclusione di qualsiasi altra istruzione tra le istruzioni END TRY e BEGIN CATCH genera un errore di sintassi.

Un costrutto TRY...CATCH non può estendersi a più batch. UN TENTATIVO... Il costrutto CATCH non può estendersi su più blocchi di istruzioni Transact-SQL. Ad esempio, un TRY... Il costrutto CATCH non può estendersi su due BEGIN... Blocchi END di istruzioni Transact-SQL e non possono estendersi su IF... Costrutto ELSE.

Se non si verificano errori nel codice racchiuso in un blocco TRY, al termine dell'esecuzione dell'ultima istruzione nel blocco TRY il controllo passa all'istruzione immediatamente successiva all'istruzione END CATCH associata.

Se si verifica un errore nel codice racchiuso in un blocco TRY, il controllo passa alla prima istruzione nel blocco CATCH associato. Al termine del codice nel blocco CATCH, il controllo passa all'istruzione immediatamente successiva all'istruzione END CATCH.

Nota

Se l'istruzione END CATCH è l'ultima istruzione in una stored procedure o un trigger, il controllo viene restituito all'istruzione che ha chiamato la stored procedure o attivato il trigger.

Gli errori intercettati da un blocco CATCH non vengono restituiti all'applicazione chiamante. Se qualsiasi parte delle informazioni sugli errori deve essere restituita all'applicazione, il codice nel blocco CATCH deve utilizzare a tale scopo meccanismi come i set di risultati SELECT o le istruzioni RAISERROR e PRINT.

I costrutti TRY...CATCH possono essere nidificati. I costrutti TRY...CATCH nidificati possono essere contenuti in un blocco TRY oppure in un blocco CATCH. Ad esempio, un blocco CATCH può contenere un costrutto TRY...CATCH incorporato per gestire gli errori rilevati dal codice CATCH.

Gli errori rilevati in un blocco CATCH vengono considerati come gli errori generati in qualsiasi altra posizione. Se il blocco CATCH contiene un costrutto TRY...CATCH nidificato, qualsiasi errore nel blocco TRY nidificato passerà il controllo al blocco CATCH nidificato. Se non esiste un costrutto TRY...CATCH nidificato, l'errore viene restituito al chiamante.

I costrutti TRY...CATCH rilevano gli errori non gestiti dalle stored procedure o dai trigger eseguiti dal codice in un blocco TRY. In alternativa, le stored procedure o i trigger possono contenere i propri costrutti TRY...CATCH per gestire gli errori generati dal proprio codice. Ad esempio, quando un blocco TRY esegue una stored procedure e si verifica un errore nella stored procedure, l'errore può essere gestito nei modi seguenti:

  • Se la stored procedure non include uno specifico costrutto TRY...CATCH, l'errore restituisce il controllo al blocco CATCH associato al blocco TRY contenente l'istruzione EXECUTE.

  • Se la stored procedure include un costrutto TRY...CATCH, l'errore trasferisce il controllo al blocco CATCH nella stored procedure. Al termine del codice del blocco CATCH, il controllo viene restituito all'istruzione immediatamente successiva all'istruzione EXECUTE che ha chiamato la stored procedure.

Le istruzioni GOTO non possono essere utilizzate per immettere un blocco TRY o CATCH. Le istruzioni GOTO possono essere utilizzate per passare a un'etichetta all'interno dello stesso blocco TRY o CATCH oppure per uscire da un blocco TRY o CATCH.

Il costrutto TRY...CATCH non può essere utilizzato in una funzione definita dall'utente.

Recupero delle informazioni sugli errori

Nell'ambito di un blocco CATCH, è possibile utilizzare le funzioni di sistema seguenti per ottenere informazioni sull'errore che ha causato l'esecuzione del blocco CATCH:

  • ERROR_NUMBER() restituisce il numero dell'errore.

  • ERROR_SEVERITY() restituisce la gravità.

  • ERROR_STATE() restituisce il numero di contesto dell'errore.

  • ERROR_PROCEDURE() restituisce il nome della stored procedure o del trigger in cui si è verificato l'errore.

  • ERROR_LINE() restituisce il numero di riga all'interno della routine che ha causato l'errore.

  • ERROR_MESSAGE() restituisce il testo completo del messaggio di errore. Il testo include i valori forniti da qualsiasi parametro sostituibile, ad esempio lunghezze, nomi di oggetti oppure orari.

Queste funzioni restituiscono NULL se vengono chiamate all'esterno dell'ambito del blocco CATCH. È possibile recuperare informazioni sugli errori utilizzando queste funzioni in qualsiasi posizione all'interno dell'ambito del blocco CATCH. Nello script seguente, ad esempio, viene illustrata una stored procedure contenente funzioni di gestione degli errori. Nel blocco CATCH di un costrutto TRY...CATCH viene chiamata la stored procedure e vengono restituite informazioni sull'errore.

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

Le funzioni ERROR_* funzionano anche in un blocco all'interno di una CATCHstored procedure compilata in modo nativo.

Errori su cui il costrutto TRY...CATCH non ha alcun effetto

I costrutti TRY...CATCH non intercettano le condizioni seguenti:

  • Avvisi o messaggi informativi con livello di gravità minore o uguale a 10.

  • Errori che hanno una gravità di 20 o superiore che arresta l'elaborazione dell'attività SQL Server motore di database per la sessione. Se si verifica un errore con livello di gravità maggiore o uguale a 20 e la connessione al database non viene interrotta, l'errore verrà gestito da TRY...CATCH.

  • Situazioni di attenzione, richieste di interruzione dei client o interruzione delle connessioni client.

  • Quando la sessione viene terminata da un amministratore di sistema tramite l'istruzione KILL.

I tipi di errore seguenti non vengono gestiti da un blocco CATCH quando si verificano allo stesso livello di esecuzione del costrutto TRY...CATCH:

  • Errori di compilazione, ad esempio errori di sintassi, che impediscono l'esecuzione di un batch.

  • Errori che si verificano durante la ricompilazione a livello di istruzione, ad esempio errori di risoluzione dei nomi degli oggetti che si verificano dopo la compilazione a causa della risoluzione dei nomi posticipata.

  • Errori di risoluzione del nome oggetto

Questi errori sono restituiti al livello che ha eseguito il batch, la stored procedure o il trigger.

In caso di errore durante la compilazione o durante la ricompilazione a livello di istruzione a un livello di esecuzione inferiore (ad esempio, durante l'esecuzione di sp_executesql o di una stored procedure definita dall'utente) all'interno del blocco TRY, l'errore si verifica a un livello inferiore rispetto al costrutto TRY...CATCH e verrà gestito dal blocco CATCH associato.

Nell'esempio seguente viene illustrato come un errore di risoluzione dei nomi degli oggetti generato da un'istruzione SELECT non venga intercettato dal costrutto TRY...CATCH, ma venga intercettato dal blocco CATCH quando la stessa istruzione SELECT viene eseguita all'interno di una stored procedure.

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  

L'errore non viene intercettato e il controllo passa dal costrutto TRY...CATCH al livello immediatamente superiore.

Eseguendo l'istruzione SELECT all'interno di una stored procedure, l'errore si verificherà a un livello inferiore rispetto al blocco TRY. L'errore verrà gestito dal costrutto 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;  

Transazioni bloccate e XACT_STATE

Se un errore generato in un blocco TRY invalida lo stato della transazione corrente, la transazione viene classificata come transazione bloccata. Un errore che normalmente termina una transazione all'esterno di un blocco TRY causa il passaggio della transazione a uno stato di transazione bloccata quando si verifica all'interno di un blocco TRY. Una transazione bloccata può eseguire soltanto le operazioni di lettura o ROLLBACK TRANSACTION. La transazione non può eseguire istruzioni Transact-SQL che genererebbero un'operazione di scrittura o un COMMIT TRANSACTION. La funzione XACT_STATE restituisce un valore -1 se una transazione è stata classificata come transazione bloccata. Al termine di un batch, il motore di database esegue il rollback di tutte le transazioni non committable attive. Se non sono stati inviati messaggi di errore al momento dell'attivazione dello stato di blocco per la transazione, al termine dell'esecuzione del batch, verrà inviato un messaggio di errore all'applicazione client. Viene così indicato che è stata rilevata una transazione bloccata e ne è stato eseguito il rollback.

Per altre informazioni sulle transazioni non committable e sulla funzione di XACT_STATE, vedere XACT_STATE (Transact-SQL).For more information about uncommittable transactions and the XACT_STATE function, see XACT_STATE (Transact-SQL).For more information about uncommittable transactions and the XACT_STATE function, see XACT_STATE (Transact-SQL).

Esempi

R. Utilizzo di TRY...CATCH

Nell'esempio seguente viene illustrata un'istruzione SELECT che genera un errore di divisione per zero. L'errore determina il passaggio dell'esecuzione al blocco CATCH associato.

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. Utilizzo di TRY...CATCH in una transazione

Nell'esempio seguente viene illustrato il funzionamento di un blocco TRY...CATCH all'interno di una transazione. L'istruzione all'interno del blocco TRY genera un errore di violazione di vincolo.

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. Utilizzo di TRY...CATCH con XACT_STATE

Nell'esempio seguente viene illustrato come utilizzare il costrutto TRY...CATCH per gestire gli errori che si verificano all'interno di una transazione. La funzione XACT_STATE determina se è necessario eseguire il commit o il rollback della transazione. In this example, l'evento SET XACT_ABORT è ON. Rende pertanto bloccata la transazione quando si verifica l'errore di violazione di vincolo.

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

D. Utilizzo di TRY...CATCH

Nell'esempio seguente viene illustrata un'istruzione SELECT che genera un errore di divisione per zero. L'errore determina il passaggio dell'esecuzione al blocco CATCH associato.

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_MESSAGE() AS ErrorMessage;  
END CATCH;  
GO  

Vedere anche

THROW (Transact-SQL)
Gravità degli errori del Motore di database
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)