TRY ... CATCH Manejo de errores y excepciones en SQL Server

La implementación de una lógica aceptable de manejo de errores en el código T-SQL es importante para evitar errores inesperados que rompan el sistema. Manejo de excepciones usando el bloque TRY… CATCH en Microsoft SQL Server es bastante idéntico al manejo de excepciones en los lenguajes de programación .NET y Java.

Fundamental básico del bloque TRY… CATCH es un grupo de sentencias que se pueden incluir en un bloque BEGIN TRY… END TRY y si ocurre algún error dentro del bloque TRY, el control se puede pasar a un grupo de sentencias escritas en un BEGIN CATCH..END CATCH bloque para manejar los errores generados en el bloque TRY.

Índice()

    Sintaxis - Bloque TRY… CATCH - SQL Server

    BEGIN TRY
        BEGIN
    	 --Group of T-SQL Statements 
        END
    END TRY
    BEGIN CATCH
        BEGIN
    	-- Group of T-SQL Statements executed when code fails in TRY 
    	--Block and  control is passed to CATCH block
        END
    END CATCH
    

    Puntos para reflexionar - TRY CATCH Manejo de excepciones - SQL Server

    1.Si el código T-SQL dentro de un bloque BEGIN TRY… END TRY se ejecuta con éxito sin fallas, entonces el código T-SQL en el bloque BEGIN CATCH..END CATCH nunca se ejecuta.

    2.El bloque BEGIN CATCH..END CATCH debe asociarse inmediatamente al lado del bloque END TRY, no se permite escribir ninguna instrucción entre END TRY y BEGIN CATCH, esto generará un error de sintaxis.

    3.Si el código T-SQL dentro del bloque BEGIN TRY… END TRY se ejecuta con éxito, entonces el control se pasa al código T-SQL inmediato escrito después del bloque END CATCH, si lo hubiera.

    4.Si surge algún error, luego de ejecutar las instrucciones en el bloque BEGIN CATCH… END CATCH, el control se pasa a la instrucción inmediata escrita después del bloque END CATCH.

    5.BEGIN TRY .. El bloque END TRY se puede anidar, podemos tener manejo de excepciones
    TRY… CATCH bloque dentro de un bloque TRY CATCH.

    Recopilación de información de error en el bloque CATCH - SQL Server

    1.NUMERO ERRONEO() - Para obtener el número de error único asociado con el error ocurrido.

    2.ERROR_SEVERITY () - Para obtener el tipo de error que ocurrió, incluye errores que puede corregir el usuario, errores fatales y no fatales.
    3.ERROR_STATE () - Para obtener el número de estado del error, para conocer la ubicación donde pudo haber ocurrido el error.
    4.ERROR_PROCEDURE () - Devuelve el nombre del procedimiento almacenado o disparador donde ocurrió el error que provocó la ejecución del bloque CATCH.
    5.MENSAJE DE ERROR() - Devuelve el mensaje de error completo, la descripción del error, como Ocurrió un error de división por cero.

    Bloque TRY..CATCH - Ejemplos de demostración - SQL Server

    Analicemos la demostración del bloque TRY..CATCH con algunos ejemplos para ayudarnos a comprender sus usos e importancia.

    1.1 - Error de división por cero - TRY..CATCH Manejo de excepciones - SQL Server

    En el siguiente ejemplo, estamos tratando de dividir un número por cero para demostrar que se ha producido el error de división por cero en un bloque TRY, y el bloque CATCH retendrá el mismo error y se mostrará la información relacionada con el error.

    1.1 - Ejemplo en acción

    BEGIN TRY
    	SELECT 1 / 0; -- Divide by Zero Error;
    END TRY
    BEGIN CATCH
    	SELECT 'We have encountered an Error'; 
    
    	SELECT  ERROR_NUMBER() AS ErrorNumber  
    	       ,ERROR_SEVERITY() AS ErrorSeverity  
    	       ,ERROR_STATE() AS ErrorState  
    	       ,ERROR_PROCEDURE() AS ErrorProcedure  
    	       ,ERROR_LINE() AS ErrorLine  
    	       ,ERROR_MESSAGE() AS ErrorMessage; 
    END CATCH
    

    1.2 Correcto - Bloque TRY… CATCH - SQL Server

    Vamos a crear una mesa Empleado con énfasis en un salario columna, considerando que el salario no puede ser cero en un mundo real, estamos agregando un VERIFICAR restricción para asegurarnos de que siempre tengamos valores distintos de cero en una columna de salario.

    Insertemos un registro con salario de 13,000, que no debería generar ningún error, por lo tanto, el control no se moverá al bloque CATCH, no se ejecutará ninguna instrucción dentro del bloque CATCH.

    En el siguiente ejemplo, la instrucción SELECT dentro de un bloque TRY se muestra correctamente, sin embargo, la instrucción SELECT dentro de un bloque CATCH no se muestra porque no vimos ningún error al ejecutar esta instrucción de inserción.

    1.2 - Ejemplo en acción

    IF OBJECT_ID('Employee') IS NOT NULL
    DROP TABLE Employee;
    
    Create table Employee
    (
        Id     INT,
        Name  VARCHAR(255),
        Salary INT CHECK (Salary > 0)
    );
    
    BEGIN TRY
        INSERT INTO Employee (Id, Name, Salary) 
        VALUES (100, 'Chetan', 13000); 
        
        SELECT 'I am in TRY Block';
    END TRY
    BEGIN CATCH
        SELECT 'Error --- I am in CATCH block';
    END CATCH
    

    TRY_CATCH_SQL_Server_Tech_Recipes_2

    1.3 Fallo - Bloque TRY… CATCH - CHECK Error de restricción - SQL Server

    En el siguiente ejemplo, estamos intentando insertar un registro de empleado con valor de salario como "0", que debería violar la restricción CHECK y generar un error.

    El siguiente código generará un error debido a la violación de la restricción CHECK, por lo tanto, el mensaje después de la instrucción Insert no se muestra y no se ejecutará ninguna otra declaración, e inmediatamente el control se pasa al bloque CATCH.

    Podemos ver que el mensaje de instrucción SELECT dentro del bloque CATCH se muestra con el mensaje de error.

    1.3 - Ejemplo en acción

    BEGIN TRY
    	INSERT INTO Employee (Id, Name, Salary) 
    	VALUES (100, 'Vish', 0); 
    	SELECT 'I am in TRY Block'; --Not Shown
    END TRY
    BEGIN CATCH
    	SELECT 'Error --- I am in catch block'; --Shown
    	SELECT  ERROR_MESSAGE(); --Shown
    END CATCH
    

    TRY_CATCH_SQL_Server_Tech_Recipes_3

    1.4 - Bloque TRY… CATCH en una TRANSACCIÓN

    Considere un escenario, queremos insertar más de un registro en la tabla de empleados y para asegurarnos de que todos los registros se inserten correctamente en la tabla de empleados, en su lugar, debería revertir cada declaración de inserción si alguno de los registros ha tenido algún error.

    Construyamos un bloque TRY..CATCH con Transaction para manejar errores y revertir todo el lote de declaraciones. Podemos ver que la tercera instrucción Insert va a violar la restricción de verificación, por lo tanto, esto generará un error y el control se pasará al bloque CATCH donde la transacción se revertirá y no se confirmará ninguna instrucción de inserción en una tabla.

    @@ TRANCOUNT - Lleve un registro del número de extractos de transacciones iniciales que se han producido en la conexión actual.

    BEGIN TRY
    	BEGIN TRANSACTION
    	INSERT INTO Employee (Id, Name, Salary)  VALUES (102, 'Niraj', 10000); 
    	INSERT INTO Employee (Id, Name, Salary) VALUES  (103, 'Chetan',  18000); 
    	INSERT INTO Employee (Id, Name, Salary) VALUES  (104, 'Vishal', 0); 
    END TRY
    BEGIN CATCH
    	IF(@@TRANCOUNT > 0)
    	ROLLBACK TRANSACtION;	
    
    	SELECT 'Transaction is Rollback, In Catch Block';
    
    	SELECT ERROR_NUMBER() 		AS ErrorNumber  
        	      ,ERROR_SEVERITY() 	AS ErrorSeverity  
    	      ,ERROR_STATE() 		AS ErrorState  
    	      ,ERROR_PROCEDURE()        AS ErrorProcedure  
                  ,ERROR_LINE() 		AS ErrorLine  
                  ,ERROR_MESSAGE() 		AS ErrorMessage; 
    END CATCH
    
    IF(@@TRANCOUNT > 0)
    COMMIT TRANSACTION;
    

    Error

    La instrucción INSERT entró en conflicto con la restricción CHECK "CK__Employee__Salary__79FD19BE". El conflicto ocurrió en la base de datos “PraticeDb”, tabla “dbo.Employee”, columna 'Salario'.

    TRY_CATCH_SQL_Server_Tech_Recipes_4

    También puede ver los archivos de SQL Server de Tech-Recipes.com para encontrar más publicaciones útiles.

    Subir