Usar @@ERROR

En SQL Server 2000 y versiones anteriores, la función @@ERROR es el medio principal de detección de errores en instrucciones de Transact-SQL. El SQL Server 2005 Database Engine (Motor de base de datos de SQL Server 2005) incorpora la construcción TRY…CATCH, que proporciona una funcionalidad mejorada. Para obtener más información, vea Usar TRY...CATCH en Transact-SQL. @@ERROR también devuelve el número de error de un error que ha encontrado la instrucción anterior. SQL Server 2005 incorpora otras funciones que proporcionan más información de error. Para obtener más información, vea Recuperar información de errores en Transact-SQL.

La función del sistema @@ERROR devuelve 0 si la última instrucción Transact-SQL se ejecutó con éxito; si la instrucción causó un error, @@ERROR devuelve el número de error. El valor de @@ERROR cambia al finalizar cada instrucción Transact-SQL.

Puesto que @@ERROR obtiene un nuevo valor cuando se completa cada instrucción Transact-SQL, procese @@ERROR de una de estas dos formas:

  • Pruebe o use @@ERROR inmediatamente después de la instrucción Transact-SQL.
  • Guarde @@ERROR en una variable de tipo entero inmediatamente después de que se complete la instrucción Transact-SQL. El valor de la variable se puede usar posteriormente.

Si la instrucción que genera el error no está en el bloque TRY de una construcción TRY…CATCH, @@ERROR debe probarse o utilizarse en la instrucción inmediatamente después de la instrucción que ha generado el error. Si la instrucción que genera el error está en un bloque TRY, @@ERROR se puede probar o utilizar en la primera instrucción del bloque CATCH asociado. En el ámbito de un bloque CATCH, la función ERROR_NUMBER se puede usar para recuperar el mismo número de error notificado por @@ERROR. ERROR_NUMBER tiene la ventaja de que está disponible para todas las instancias del ámbito del bloque CATCH, mientras que @@ERROR se restablece mediante la primera instrucción del bloque CATCH.

Las instrucciones condicionales, como la instrucción IF, restablecen @@ERROR. Si hace referencia a @@ERROR en una instrucción IF, las referencias a @@ERROR en los bloques IF o ELSE no recuperarán la información de @@ERROR. En el siguiente ejemplo, @@ERROR ha sido restablecido por IF y no devuelve el número de error cuando se le hace referencia en la instrucción 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

En el siguiente ejemplo se devuelven los resultados esperados.

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

Si desea hacer referencia a @@ERROR y @@ROWCOUNT después de ejecutar una instrucción, deben tener una referencia en la misma instrucción. @@ERROR y @@ROWCOUNT se restablecen con cada instrucción Transact-SQL; por lo tanto, debe hacerse referencia a ambas en la misma instrucción inmediatamente después de la que se prueba. En el siguiente ejemplo, @@ROWCOUNT siempre será 0 porque no se hace referencia a ella hasta que se restablece mediante la primera instrucción PRINT.

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

En el siguiente ejemplo se devuelven los resultados esperados.

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

@@ERROR se genera sólo para errores, no para advertencias; los lotes, procedimientos almacenados y desencadenadores no pueden usar @@ERROR para detectar advertencias que se hayan producido.

Una de las utilizaciones más comunes de @@ERROR en SQL Server 2000 y versiones anteriores es indicar si un procedimiento almacenado se ha ejecutado correctamente o no. Una variable de tipo entero se inicializa a 0. Una vez completada cada instrucción Transact-SQL, se comprueba que @@ERROR sea 0 y, si no lo es, se almacena en la variable. A continuación, el procedimiento devuelve la variable en la instrucción RETURN. Si en ninguna de las instrucciones Transact-SQL del procedimiento se produjera un error, la variable permanecería con el valor 0. Si una o varias instrucciones generaran un error, la variable contendría el último número de error. En el siguiente ejemplo se muestra un procedimiento almacenado simple con esta lógica.

USE AdventureWorks;
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, Title
        FROM HumanResources.Employee
        WHERE EmployeeID = @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

@@ERROR frente a TRY...CATCH

El uso de @@ERROR como medio principal de detección de errores conduce a un código de gestión de errores de estilo muy diferente del que se utiliza con construcciones TRY…CATCH.

  • @@ERROR debe comprobarse o guardarse después de cada instrucción Transact-SQL porque un programador no puede predecir qué instrucción puede generar un error. Esto dobla el número de instrucciones Transact-SQL que deben codificarse para implementar un fragmento de lógica dado.
  • Las construcciones TRY…CATCH son mucho más simples. Un bloque de instrucciones Transact-SQL está delimitado por instrucciones BEGIN TRY y END TRY y después se escribe un bloque CATCH para gestionar errores que pueden generarse mediante el bloque de instrucciones.

Fuera de un bloque CATCH, @@ERROR es la única parte de un error de Database Engine (Motor de base de datos) disponible en el lote, procedimiento almacenado o desencadenador que ha generado el error. El resto de las partes del error, como su gravedad, estado y texto del mensaje que contienen cadenas de sustitución (nombres de objeto, por ejemplo) sólo se devuelven a la aplicación, donde pueden procesarse mediante los mecanismos de control de errores de las API. Si el error invoca un bloque CATCH, se pueden usar las funciones del sistema ERROR_LINE, ERROR_MESSAGE, ERROR_PROCEDURE, ERROR_NUMBER, ERROR_SEVERITY y ERROR_STATE.

Vea también

Conceptos

Usar RAISERROR
Controlar errores y mensajes en las aplicaciones
Usar TRY...CATCH en Transact-SQL

Otros recursos

@@ERROR (Transact-SQL)
TRY...CATCH (Transact-SQL)
ERROR_LINE (Transact-SQL)
ERROR_MESSAGE (Transact-SQL)
ERROR_NUMBER (Transact-SQL)
ERROR_PROCEDURE (Transact-SQL)
ERROR_SEVERITY (Transact-SQL)
ERROR_STATE (Transact-SQL)

Ayuda e información

Obtener ayuda sobre SQL Server 2005