lunes, 10 de marzo de 2014

Introducción a las transacciones en SQL Server

Escribes código. Lo pruebas. Funciona. Lo pones en producción. ¿Y qué pasa? Falla y ahora tienes datos sucios en la base de datos. Cuando hablamos de datos sucios nos referimos a datos probablemente incompletos o, quizás, carentes de sentido.

Quizás tienes un procedimiento almacenado (Stored Procedure) que realiza cambios (insertar, actualizar, borrar) en una o varias tablas consecutivamente, donde una operación depende de la anterior, o al menos, le da sentido. Por ejemplo: si en la base de datos de una tienda tienes una tabla para la cabecera de las facturas (datos generales: nombre del cliente, fecha de la compra, sucursal, etc.) y otra tabla para el detalle de la factura (el listado de artículos que se compró en dicha orden), es evidente que no tiene sentido un registro de cabecera que no tenga sus correspondientes registros de detalle.

Supongamos que surge un problema cuando insertamos los datos de los artículos en la tabla de detalles. Supongamos que de 3 artículos en la tabla de detalles, solo se insertaron dos, hubo un error con el tercero. Por eso, tenemos ahora datos incoherentes. Probablemente la factura dice un total de la orden pero la sumatoria de los precios de los artículos no da como resultado dicho total.

Para prevenir estos casos usaremos transacciones.

Las transacciones son un concepto fácil de entender. Imagina una transacción como un conjunto de operaciones la cual puedes revertir antes de un momento dado. Es como cuando abres un documento de texto y empiezas a escribir, por más que escribas, si no guardas tu progreso, todos los cambios que has hecho se pueden revertir rápidamente cerrando el documento sin guardarlo. Una transacción, hasta que no la "salves", la puedes revertir.

Haremos un ejemplo bastante simple para ver el poder de las transacciones. Pero primero, por si acaso, hablemos de los bloques Try y Catch. Cuando ocurre un error en tu aplicación, es posible que esta simplemente se detenga y te muestre un mensaje de error. Sin embargo, si el código que generó el error está dentro de un bloque "Try", en vez de la aplicación terminar su ejecución al ocurrir el error, simplemente correrá un código dentro del bloque Catch (el cual debes escribir). Si no ocurre un error, el código del bloque Catch no se ejecuta. Considera el bloque Catch como una manera de limpiar el desastre tras un error.

Para entender el ejemplo que vamos a ver, necesitas saber:
- Begin Transaction: se utiliza para indicar desde donde inicia una transacción. Lo ideal es que lo que está dentro de un bloque de transacción son operaciones que dependen entre sí de alguna forma. Donde, si una operación falla, queremos revertir todo lo que hallamos hecho dentro del bloque de transacción.
- Commit Transaction: es el equivalente a salvar los datos de la transacción.
- Rollback Transaction: sirve para revertir los cambios hechos durante la transacción ANTES de haber llegado a ejecutar algún Commit Transaction.
- @@Trancount: devuelve el número de transacciones activas.

Ahora, veamos el ejemplo.

BEGIN TRY;
  BEGIN TRANSACTION;
INSERT INTO tblTest(Name)
VALUES ('Valor');
RAISERROR ('Hola, soy un error :(', 18, 34);
COMMIT TRANSACTION;
END TRY

BEGIN CATCH;
PRINT Error_Message();
if @@TRANCOUNT > 0
ROLLBACK TRANSACTION;
END CATCH

En el estado original del ejemplo, los cambios no serán "guardados", por lo que el Insert "no tendrá efecto". Esto sucede por la linea que dice RaiseError, que sirve para emitir un error. Dado que hubo un error, el código en el bloque try deja de ejecutarte a partir de la linea que genera el error y pasa a ejecutarse el código del bloque catch. Si borras la linea del RaiseError, entonces el Commit Transaction se ejecuta y los cambios hechos dentro de la transacción serán guardados. En este caso, el Rollback Transaction nunca se ejecuta.

¡Felicidades! Ya sabes usar transacciones, al menos en un nivel un tanto simple. Y realmente es así, el ejemplo que vimos fue más para que entiendas la importancia de las transacciones y sepas implementarlas. Aunque no lo parezca, este es un gran paso. No importa cuán seguro estés de tu código, es bueno saber que en caso de que algo malo ocurra, las transacciones estarán ahí para salvarte.

No hay comentarios:

Publicar un comentario