¡Hola, chicos!
¡Primer post de 2019!
En este artículo explicaré la diferencia entre @@ERROR y la función ERROR_NUMBER(), que en teoría trae el mismo resultado, es decir, la cantidad de errores causados por alguna operación en la sesión actual. La idea de escribir sobre esto surgió a partir de una pregunta de un nigeriano en el grupo Servidor SQL – DBA, de Telegram y pensé que sería genial publicar esta explicación en mi blog para ayudar a otras personas con la misma pregunta.
Primero, consultemos la documentación oficial de Microsoft para ver si tenemos alguna pista sobre la diferencia entre estos 2 métodos:
Devuelve el número de error de la última instrucción Transact-SQL ejecutada. Devuelve 0 si la instrucción Transact-SQL anterior no encontró ningún error.
Dado que @@ERROR se borra y restablece en cada declaración ejecutada, consúltelo inmediatamente después de verificar la declaración o guárdelo en una variable local que pueda verificarse más tarde.
Esta función devuelve el número de error que provocó la ejecución del bloque CATCH de una construcción TRY…CATCH. Cuando se llama en un bloque CATCH, ERROR_NUMBER devuelve el número del error que provocó la ejecución del bloque CATCH. ERROR_NUMBER devuelve NULL cuando se llama fuera del alcance de un bloque CATCH.
ERROR_NUMBER devuelve un número de error relevante independientemente de cuántas veces o dónde se ejecuta dentro del alcance del bloque CATCH. Esto es diferente de una función como @@ERROR, que solo devuelve un número de error en la declaración inmediatamente posterior a la que causa el error.
En un bloque CATCH anidado, ERROR_NUMBER devuelve el número del error específico del alcance del bloque CATCH que hace referencia a este bloque CATCH. Por ejemplo, el bloque CATCH de una construcción TRY…CATCH externa podría tener una construcción TRY…CATCH interna. Dentro de este bloque CATCH interno, ERROR_NUMBER devuelve el número del error que invocó el bloque CATCH interno. Si se ejecuta ERROR_NUMBER en el bloque CATCH externo, devuelve el número del error que invocó ese bloque CATCH externo.
Analizando la documentación, queda clara la diferencia entre estos 2 métodos para identificar el código de error:
- @@ERROR: Devuelve el código de error de la última instrucción ejecutada (con cada nueva instrucción, la variable se restablece a cero). Devuelve 0 si no hay error o si la variable es cero. Se recomienda asignar el resultado @@ERROR a una variable local justo al comienzo de CATCH, ya que CUALQUIER COMANDO hace que @@ERROR se restablezca (incluso un SELECT @@ERROR).
- NÚMERO_ERROR: Devuelve el código de error dentro del alcance de un bloque CATCH. Devuelve NULL si intenta utilizar el comando fuera de un bloque CATCH
Y ahora, ¡veamos cómo funciona esto en la práctica!
BEGIN TRY
SELECT 1/0
END TRY
BEGIN CATCH
-- Os 2 comandos vão trazer o mesmo retorno
SELECT ERROR_NUMBER() AS [ERROR_NUMBER_1], @@ERROR AS [@@ERROR_1]
BEGIN TRY
EXEC('SELECT * FROM dbo.Teste_123')
END TRY
BEGIN CATCH
/*
Aqui, vou colocar um comando PRINT para "atrapalhar" o comportamento do @@ERROR
Como o @@ERROR é resetado a cada comando executado, o PRINT vai fazer com que a variável @@ERROR seja zerada
*/
PRINT 'Esse print vai atrapalhar o @@ERROR'
SELECT ERROR_NUMBER() AS [ERROR_NUMBER_2], @@ERROR AS [@@ERROR_2]
BEGIN TRY
EXEC dbo.stpTeste
END TRY
BEGIN CATCH
-- Aqui nada de novo também.. os 2 terão o mesmo retorno
SELECT ERROR_NUMBER() AS [ERROR_NUMBER_3], @@ERROR AS [@@ERROR_3]
-- Mas se eu tentar executar novamente o comando... o ERROR_NUMBER permanece igual, enquanto o @@ERROR já foi zerado
SELECT ERROR_NUMBER() AS [ERROR_NUMBER_3_DENOVO], @@ERROR AS [@@ERROR_3_DENOVO]
END CATCH
END CATCH
/*
Já aqui, o ERROR_NUMBER vai retornar a mensagem de erro do bloco 1, que é o escopo atual do bloco CATCH
Já a variável @@ERROR ficará vazia, pois outros comandos foram executados depois da última mensagem de erro
*/
SELECT ERROR_NUMBER() AS [ERROR_NUMBER_VOLTOU_PRO_1], @@ERROR AS [@@ERROR_ZERADO_PORQUE_OUTRO_COMANDO_JA_FOI_EXECUTADO]
END CATCH
-- Por fim, como o ERROR_NUMBER() não está dentro de nenhum bloco de CATCH com erro, retornará NULL e a @@ERROR retornará 0
SELECT ERROR_NUMBER() AS [ERROR_NUMBER_FINAL], @@ERROR AS [@@ERROR_FINAL]
Pero, ¿qué pasa si no estoy usando TRY..CATCH y quiero capturar el código de error? ¿Puedo utilizar cualquiera de los dos métodos?

Respuesta: ¡NO! sí No está dentro de un bloque TRY..CATCH, la función ERROR_NUMBER() devolverá NULL, mientras que la variable @@ERROR devolverá el código de error (recuerda las condiciones de uso de @@ERROR para evitar que se resetee y pierdas esta información).
¡Y eso es todo, amigos!
Publicación muy breve y objetiva y espero que haya ayudado a aclarar la diferencia entre @@ERROR y ERROR_NUMBER().
Y recuerda: UTILIZA INTENTAR... ¡ATRAPAR!
¡Que tengas un buen 2019 y nos vemos en el próximo artículo!
¡Gran abrazo!

Comentários (0)
Carregando comentários…