La Try…Catch di Sql Server 2005

E finalmente anche TSQL ebbe una gestione degli errori un po’ più “programmer’s oriented”! Con Sql Server 2005 infatti è stata introdotta la gestione della TRY....CATCH simile a quella a cui siamo abituati programmando – ad esempio – con .NET. Rispetto ai classici linguaggi di programmazione, la gestione è un po’ più grezza, ad esempio manca la clausola FINALLY, utile per liberare risorse indipendentemente dall’esito delle operazioni, però si può cominciare a ragionare.

Lo script qui sotto presentato non ha una vera utilità pratica, ma piuttosto ha una valore didattico, dal momento che si prefigge lo scopo di chiarire l’ordine di esecuzione delle istruzioni in presenza di un errore trappato con la TRY...CATCH.

Cominciamo col dire che il blocco di codice da “proteggere” va scritto entro le due istruzioni BEGIN TRY ... END TRY (corrispondente alla Try di Visual Basic.NET, per capirci); il codice da eseguire in caso di errore (il blocco Catch) deve essere invece racchiuso entro le keyword BEGIN CATCH ... END CATCH. In caso di errore verrà eseguito tutto il codice contenuto nel blocco CATCH, anche se al suo interno venisse richiamata una Raiserror.

Per dimostrare il funzionamento della TRY...CATCH, creerò una stored procedure che genererà un errore; il codice di ritorno viene impostato a -100 nel codice sorgente, ma solo dopo che è stata innalzata un eccezione. Vediamo cosa succede:

IF EXISTS (SELECT * FROM sys.objects WHERE [name] = 'TestCatch' )
  DROP PROCEDURE [dbo].[TestCatch];
GO

CREATE PROCEDURE [dbo].[TestCatch]
AS
BEGIN
  DECLARE @emes nvarchar( max )
        , @esev int
        , @esta int;

  SET @esev = 0;

  PRINT '[dbo].[TestCatch].Entering TRY...CATCH';

  BEGIN TRY
    PRINT '[dbo].[TestCatch]....Into the WILD';
    RAISERROR ('- MESSAGGIO DI ERRORE SIMULATO -', 15, 9);

    /* Il codice da qui in poi NON viene eseguito */
    PRINT '[dbo].[TestCatch]....Into the WILD again - will never get here';
    RETURN -100;

  END TRY

  BEGIN CATCH
    /* Tutto il codice nel blocco CATCH viene sempre seguito */
    PRINT '[dbo].[TestCatch]....Into the CATCH';
    SELECT @emes = ERROR_MESSAGE()
         , @esev = ERROR_SEVERITY()
         , @esta = ERROR_STATE();
    RAISERROR ( @emes, @esev, @esta );
    PRINT '[dbo].[TestCatch]....Into the CATCH again';

  END CATCH

  PRINT '[dbo].[TestCatch].Out of TRY...CATCH';

  IF NOT @emes IS NULL
  BEGIN
    RAISERROR( @emes , @esev , @esta );
    PRINT '[dbo].[TestCatch].Raising external error';
  END

  RETURN -@esta;
END
GO

Richiamando la stored procedure, vediamo un po’ quale valore e quale output restituisce.

DECLARE @rc int;
EXECUTE @rc = [dbo].[TestCatch];
SELECT @rc;
GO

Il valore resitituito dalla SELECT @rc è:

-9

L’output generato dalle varie PRINT e RAISERROR invece è il seguente:

[dbo].[TestCatch].Entering TRY...CATCH
[dbo].[TestCatch]....Into the WILD
[dbo].[TestCatch]....Into the CATCH
Msg 50000, Level 15, State 9, Procedure TestCatch, Line 28
- MESSAGGIO DI ERRORE SIMULATO -
[dbo].[TestCatch]....Into the CATCH again
[dbo].[TestCatch].Out of TRY...CATCH
Msg 50000, Level 15, State 9, Procedure TestCatch, Line 37
- MESSAGGIO DI ERRORE SIMULATO -
[dbo].[TestCatch].Raising external error

(1 row(s) affected)

Come si può notare dalle varie stringhe stampate e – soprattutto – da quelle non stampata, la RAISERROR contenuta nel blocco TRY passa il controllo del codice al blocco CATCH: il codice nel blocco TRY successivo all’errore non viene eseguito; al contrario, tutto il blocco all’interno del blocco CATCH viene eseguito, anche quello successivo alla RAISERROR.

Giusto a titolo di curiosità, vediamo un po’ cosa succede se commentiamo la RAISERROR contenuta all’interno del blocco Catch. Il valore restituitè è esattamente lo stesso:

-9

mentre l’output generato è leggermente differente (ovviamente), mancando la riga generata dalla RAISERROR

[dbo].[TestCatch].Entering TRY...CATCH
[dbo].[TestCatch]....Into the WILD
[dbo].[TestCatch]....Into the CATCH
[dbo].[TestCatch]....Into the CATCH again
[dbo].[TestCatch].Out of TRY...CATCH
Msg 50000, Level 15, State 9, Procedure TestCatch, Line 37
- MESSAGGIO DI ERRORE SIMULATO -
[dbo].[TestCatch].Raising external error

(1 row(s) affected)

Lascia un commento

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *

*