Utilizzo di @@ERROR
La funzione di sistema @@ERROR restituisce 0 se l'ultima istruzione Transact-SQL è stata eseguita correttamente oppure un numero di errore se l'istruzione ha generato un errore. Il valore di @@ERROR cambia ogni volta che un'istruzione Transact-SQL viene completata.
La funzione @@ERROR deve essere pertanto elaborata in uno dei due modi seguenti:
Testare o utilizzare @@ERROR subito dopo l'istruzione Transact-SQL.
Salvare @@ERROR in una variabile di tipo integer subito dopo il completamento dell'istruzione Transact-SQL. Il valore della variabile potrà essere utilizzato in un secondo momento.
Se l'istruzione che genera l'errore non è inclusa nel blocco TRY di un costrutto TRY…CATCH, è necessario testare la funzione @@ERROR o utilizzarla nell'istruzione subito dopo quella che ha generato l'errore. Se l'istruzione che genera l'errore è inclusa in un blocco TRY, è possibile testare o utilizzare la funzione @@ERROR nella prima istruzione del blocco CATCH associato. Nell'ambito di un blocco CATCH è possibile utilizzare la funzione ERROR_NUMBER per recuperare lo stesso numero di errore restituito da @@ERROR. ERROR_NUMBER è disponibile per tutte le istruzioni incluse nell'ambito del blocco CATCH, mentre la funzione @@ERROR viene reimpostata dalla prima istruzione del blocco CATCH.
La funzione @@ERROR viene reimpostata da istruzioni condizionali, quali l'istruzione IF. Se viene fatto riferimento alla funzione @@ERROR in un'istruzione IF, i riferimenti a @@ERROR nei blocchi IF o ELSE non consentiranno di recuperare le informazioni su @@ERROR. Nell'esempio seguente la funzione @@ERROR viene reimpostata da IF e non restituisce il numero di errore quando vi viene fatto riferimento nell'istruzione PRINT.
DECLARE @ErrorVar INT
RAISERROR(N'Message', 16, 1);
IF @@ERROR <> 0
-- This PRINT statement prints 'Error = 0' because
-- @@ERROR is reset in the IF statement above.
PRINT N'Error = ' + CAST(@@ERROR AS NVARCHAR(8));
GO
Nell'esempio seguente vengono restituiti i risultati previsti.
DECLARE @ErrorVar INT
RAISERROR(N'Message', 16, 1);
-- Save the error number before @@ERROR is reset by
-- the IF statement.
SET @ErrorVar = @@ERROR
IF @ErrorVar <> 0
-- This PRINT statement correctly prints 'Error = 50000'.
PRINT N'Error = ' + CAST(@ErrorVar AS NVARCHAR(8));
GO
Se si desidera fare riferimento sia a @@ERROR che a @@ROWCOUNT dopo l'esecuzione di un'istruzione, è necessario includerle nella stessa istruzione. @@ERROR e @@ROWCOUNT vengono reimpostati dopo ogni istruzione Transact-SQL, pertanto è necessario farvi riferimento nella stessa istruzione subito dopo quella di cui è in corso il test. Nell'esempio seguente il valore di @@ROWCOUNT sarà sempre 0 perché a tale funzione non viene fatto riferimento finché non viene reimpostata dalla prima istruzione PRINT.
USE AdventureWorks2008R2;
GO
DELETE FROM HumanResources.JobCandidate
WHERE JobCandidateID = 13;
-- This PRINT would successfully capture any error number.
PRINT N'Error = ' + CAST(@@ERROR AS NVARCHAR(8));
-- This PRINT will always print 'Rows Deleted = 0 because
-- the previous PRINT statement set @@ROWCOUNT to 0.
PRINT N'Rows Deleted = ' + CAST(@@ROWCOUNT AS NVARCHAR(8));
GO
Nell'esempio seguente vengono restituiti i risultati previsti.
USE AdventureWorks2008R2;
GO
DECLARE @ErrorVar INT;
DECLARE @RowCountVar INT;
DELETE FROM HumanResources.JobCandidate
WHERE JobCandidateID = 13;
-- Save @@ERROR and @@ROWCOUNT while they are both
-- still valid.
SELECT @ErrorVar = @@ERROR,
@RowCountVar = @@ROWCOUNT;
IF (@ErrorVar <> 0)
PRINT N'Error = ' + CAST(@ErrorVar AS NVARCHAR(8));
PRINT N'Rows Deleted = ' + CAST(@RowCountVar AS NVARCHAR(8));
GO
La funzione @@ERROR viene eseguita solo in caso di errore, non per gli avvisi. Di conseguenza non è possibile utilizzare @@ERROR in batch, stored procedure e trigger per rilevare gli eventuali avvisi visualizzati.
La funzione @@ERROR viene in genere utilizzata in SQL Server 2000 e nelle versioni precedenti per indicare se una stored procedure ha avuto esito positivo o negativo. Una variabile di tipo integer viene inizializzata su 0. Dopo il completamento dell'istruzione Transact-SQL, viene verificato il valore di @@ERROR. Se è diverso da 0, il valore viene archiviato nella variabile. La stored procedura restituisce quindi la variabile dell'istruzione RETURN. Se nessuna istruzione Transact-SQL della procedura ha generato errori, il valore della variabile rimane 0. Se invece una o più istruzioni hanno generato un errore, nella variabile verrà archiviato il numero dell'ultimo errore. Nell'esempio seguente viene illustrata una stored procedure in cui è stata applicata la logica descritta.
USE AdventureWorks2008R2;
GO
IF EXISTS(SELECT name FROM sys.objects
WHERE name = N'SampleProcedure')
DROP PROCEDURE SampleProcedure;
GO
-- Create a procedure that takes one input parameter
-- and returns one output parameter and a return code.
CREATE PROCEDURE SampleProcedure @EmployeeIDParm INT,
@MaxVacation INT OUTPUT
AS
-- Declare and initialize a variable to hold @@ERROR.
DECLARE @ErrorSave1 INT, @ErrorSave2 INT;
SET @ErrorSave1 = 0;
-- Do a SELECT using the input parameter.
SELECT LoginID, NationalIDNumber, JobTitle
FROM HumanResources.Employee
WHERE BusinessEntityID = @EmployeeIDParm;
-- Save @@ERROR value in first local variable.
SET @ErrorSave1 = @@ERROR;
-- Set a value in the output parameter.
SELECT @MaxVacation = MAX(VacationHours)
FROM HumanResources.Employee;
-- Save @@ERROR value in second local variable.
SET @ErrorSave2 = @@ERROR;
-- If second test variable contains non-zero value,
-- overwrite value in first local variable.
IF (@ErrorSave2 <> 0) SET @ErrorSave1 = @ErrorSave2;
-- Returns 0 if neither SELECT statement had
-- an error; otherwise, returns the last error.
RETURN @ErrorSave1;
GO
DECLARE @OutputParm INT;
DECLARE @ReturnCode INT;
EXEC @ReturnCode = SampleProcedure 13, @OutputParm OUTPUT;
PRINT N'OutputParm = ' + CAST(@OutputParm AS NVARCHAR(20));
PRINT N'ReturnCode = ' + CAST(@ReturnCode AS NVARCHAR(20));
GO
Confronto tra @@ERROR e TRY...CATCH
Se si utilizza la funzione @@ERROR come mezzo principale per la rilevazione degli errori, si otterrà codice di gestione degli errori molto diverso rispetto a quello utilizzato con i costrutti TRY…CATCH.
È necessario testare o salvare la funzione @@ERROR dopo ogni istruzione Transact-SQL perché uno sviluppatore non può prevedere in anticipo l'istruzione che potrebbe generare un errore. In tal modo risulta raddoppiato il numero di istruzioni Transact-SQL da codificare per implementare una determinata logica.
I costrutti TRY…CATCH sono molto più semplici. Un blocco di istruzioni Transact-SQL viene racchiuso tra istruzioni BEGIN TRY e END TRY e quindi viene scritto un blocco CATCH per gestire gli errori che potrebbero essere generati da tale blocco di istruzioni.
All'esterno di un blocco CATCH block, la funzione @@ERROR rappresenta l'unico elemento di un errore di Motore di database disponibile nel batch, nella stored procedure o nel trigger che ha generato l'errore. Tutti gli altri elementi dell'errore, quali il livello di gravità, lo stato e il testo del messaggio contenente stringhe di sostituzione, ad esempio il nome dell'oggetto, verranno restituiti solo all'applicazione in cui possono essere elaborati tramite le funzioni di gestione degli errori API. Se l'errore richiama un blocco CATCH, sarà possibile utilizzare le funzioni di sistema ERROR_LINE, ERROR_MESSAGE, ERROR_PROCEDURE, ERROR_NUMBER, ERROR_SEVERITY e ERROR_STATE.
Vedere anche