Realizando una transacción en SQL Server


Por norma general, me gusta codificar la lógica de acceso a datos en programa, en lugar de en procedimientos almacenados en base de datos. Esta aproximación no es muy óptima (como se suele decir, al César lo que es del César y a Dios lo que es de Dios), ya que el entorno transaccional estará mejor gestionado por el SGBD que por el código .NET.
Si queremos trasladar la responsabilidad de gestionar la transacción al SGBD, deberemos saber en primer lugar que se declara del siguiente modo:

BEGIN TRAN
 -- Ejecución de sentencias
COMMIT TRAN

Como imaginaremos, la primera sentencia “arranca” la transacción, mientras que la última la compromete. Pero ¿y si ocurre un error en alguna de las sentencias? ¿Cómo lo detectamos?
En el siguiente ejemplo, utilizaremos variables enteras para trazar los fallos y realizar un ROLLBACK en el caso de que la transacción falle.

Se declarará una variable de tipo INT por cada sentencia a ejecutar, y se inician a 0. Se comprueba, después de cada sentencia ejecutada, la variable @@Error, y se almacena en las variables anteriormente creadas. Si es distinta de 0, hay un error, por lo que se añade información al mensaje de error.
Al final de la transacción, si todas las variables son 0, se hace el COMMIT. Si una de ellas es distinta de cero, significará que existe un error y se hace el Rollback, mostrando el mensaje de error.


DECLARE @CadenaError varchar(1000);
 DECLARE @CodigosError varchar(1000);
 DECLARE @ErrorSentencia1 int;
 DECLARE @ErrorSentencia2 int;
 DECLARE @ErrorSentencia3 int;

 SET @ErrorSentencia1 = 0;
 SET @ErrorSentencia2 = 0;
 SET @ErrorSentencia3 = 0;

 SET @CadenaError = 'Error al realizar actualización: ';
 SET @CodigosError = 'Códigos de error: ';

 -- Inicio de la transacción
 BEGIN TRAN

 -- Primera actualización
 UPDATE Usuario SET Nombre = 'Elena' WHERE Nombre = "Helena";

 -- Almacenamos el posible código de error
 SET @ErrorSentencia1 = @@Error;
 IF (@ErrorSentencia1  0)
 BEGIN
     SET @CadenaError = @CadenaError + 'Actualización 1; '
     SET @CodigosError = @CodigosError + CAST(@ErrorSentencia1 AS VARCHAR(10)) + '; ';
 END

 -- Segunda actualización
 UPDATE Perfil SET Nombre = 'Administrador' WHERE Nombre = "Admin";

 -- Almacenamos el posible código de error
 SET @ErrorSentencia2 = @@Error;
 IF (@ErrorSentencia2  0)
 BEGIN
     SET @CadenaError = @CadenaError + 'Actualización 2; '
     SET @CodigosError = @CodigosError + CAST(@ErrorSentencia2 AS VARCHAR(10)) + '; ';
 END

 -- Tercera actualización
 UPDATE UsuarioPerfil SET CodigoUsuario = 1 WHERE CodigoPerfil < 3;

 -- Almacenamos el posible código de error
 SET @ErrorSentencia3 = @@Error;
 IF (@ErrorSentencia3  0)
 BEGIN
     SET @CadenaError = @CadenaError + 'Actualización 3; '
     SET @CodigosError = @CodigosError + CAST(@ErrorSentencia3 AS VARCHAR(10)) + '; ';
 END

 -- En ausencia de errores, comprometemos la transacción
 IF (@ErrorSentencia1 = 0) AND (@ErrorSentencia2 = 0) AND (@ErrorSentencia3 = 0)

BEGIN
     COMMIT TRAN;
     PRINT('Transacción realizada con éxito');
 END
 ELSE
 BEGIN
     ROLLBACK TRAN;
     PRINT('Transacción abortada');
     PRINT(@CadenaError);
     PRINT(@CodigosError);
 END

Con todo esto, obtendremos suficiente información (esperemos) como para detectar donde está el fallo.

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