T-SQL: Crear errores custom en un SP

¿Puedo crear mis propios errores en un SP y forzar la detención de un Procedimiento Almacenado? Por supuesto que sí.

Para empezar deberíamos empezar trabajando con un TRY/CATCH ¿Existe en SQL? Sí, pero no funciona de la misma forma que lo hace en los lenguajes de programación convencionales. Verán, el CATCH de T-SQL no captura interrupciones como las excepciones. El CATCH es genérico y se va a él cuándo sucede cualquier tipo de error durante la ejecución de un procedimiento.

Para crear nuestros propios errores vamos a usar la función RAISERROR() (cuidado con confundirla con RAISEERROR porque son distintas).Lo importante de esta función es entender que tiene tres componentes en el siguiente orden:

  1. El mensaje a enviar
  2. La severidad (detallo más abajo)
  3. El estado

La más importante es el valor que le ponemos en severidad. Si queremos que por una situación dada dar el error e ir al CATCH, tenemos que dejar la severidad en un valor del 11 al 18. Si queremos que se corte la conexión al usuario, necesitamos una severidad entre 20 y 25 (pero este caso solo lo puede implementar un sysadmin). Si queremos que se elija por default, le dejamos -1.

Aquí va un código de ejemplo:

CREATE PROCEDURE dbo.TEST
AS
BEGIN
	BEGIN TRY
	DECLARE @variable INT = 1

	IF @variable = 1
		RAISERROR('Aca escribo mi error', 11,1)

	END TRY
	BEGIN CATCH
	    DECLARE @ErrorMessage NVARCHAR(4000);
		DECLARE @ErrorSeverity INT;
		DECLARE @ErrorState INT;  

		SELECT
			@ErrorMessage = ERROR_MESSAGE(),
			@ErrorSeverity = ERROR_SEVERITY(),
			@ErrorState = ERROR_STATE();  

		-- Use RAISERROR inside the CATCH block to return error
		-- information about the original error that caused
		-- execution to jump to the CATCH block.
		RAISERROR (@ErrorMessage, -- Message text.
				   @ErrorSeverity, -- Severity.
				   @ErrorState -- State.
				   );
	END CATCH
END

Lo que está dentro del CATCH es para capturar desde el sistema cual es el mensaje de error que se recibió. Si nuestro SP no falla donde nosotros controlamos pero si por ejemplo en un INSERT o un UPDATE, entonces va a salir y dar el error de esa consulta.

Finalmente hagan un EXEC del SP y vean que les devuelve.

Todo esto fue para versiones de SQL Server 2012 hacia atrás. Desde la versión 2012 en adelante Microsoft empieza a recomendar usar THROW. Replicando el ejemplo anterior, tendríamos que usar el siguiente código.

DROP PROCEDURE dbo.TEST

GO
CREATE PROCEDURE dbo.TEST
AS
BEGIN
	BEGIN TRY
	DECLARE @variable INT = 1

	IF @variable = 1
		THROW 50000, 'Aca escribo mi error', 1

	END TRY
	BEGIN CATCH
	    THROW
	END CATCH
END

El throw no tiene severidad (por default es siempre 16). También existen varias diferencias con el RAISERROR. Si necesitan saberlas, les recomiendo el siguiente link con scripts para comparar ambos: Differences Between RAISERROR and THROW in Sql Server.

Saludos,
Alejandro

Deja un comentario

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s