Veamos ahora un ejemplo
de transacción anidada con ROLLBACK TRAN
BEGIN
TRAN TranExterna -- @@TRANCOUNT ahora es 1
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (1)
BEGIN TRAN TranInterna1 -- @@TRANCOUNT ahora es 2.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (2)
BEGIN TRAN TranInterna2 -- @@TRANCOUNT ahora es 3.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (3)
ROLLBACK TRAN --@@TRANCOUNT es 0 y se deshace
--la transacción externa y todas las internas
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
SELECT
* FROM Test
En este caso no se inserta
nada puesto que el ROLLBACK TRAN deshace todas las transacciones dentro
de nuestro anidamiento hasta la transacción más externa y
además hace @@TRANCOUNT=0
¿Supone este funcionamiento
asimétrico del COMMIT y del ROLLBACK un problema?
Pues la verdad es que no.
La manera de tratar las transacciones por el SQL Server es la que nos permite
programar de manera natural los anidamientos.
De todos modos, si queremos
ir un poco más lejos hay una cuarta sentencia para trabajar con
transacciones: SAVE TRAN
SAVE TRAN
Esta sentencia crea un punto
de almacenamiento dentro de una transacción. Esta marca sirve para
deshacer una transacción en curso sólo hasta ese punto. Por
supuesto nuestra transacción debe continuar y terminar con un COMMIN
TRAN (o los que hagan falta) para que todo se guarde o con un ROLLBACK
TRAN para volver al estado previo al primer BEGIN TRAN.
BEGIN
TRAN TranExterna -- @@TRANCOUNT ahora es 1
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (1)
BEGIN TRAN TranInterna1 -- @@TRANCOUNT ahora es 2.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (2)
SAVE TRAN Guadada
BEGIN TRAN TranInterna2 -- @@TRANCOUNT ahora es 3.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
INSERT INTO Test VALUES (3)
ROLLBACK TRAN Guadada -- se deshace lo hecho el punto guardado.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
--Ahora podemos decidir si la transacción se lleva a cabo
--o se deshace completamente
--Para deshacerla un ROLLBACK bastará como hemos visto
--Pero para guardar la transacción hace falta reducir @@TRANCOUNT
a 0
COMMIT TRAN TranInterna1 -- Reduce @@TRANCOUNT a 2.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
COMMIT
TRAN TranInterna1 -- Reduce @@TRANCOUNT a 1.
-- Pero no se guarda nada en la base de datos.
SELECT 'El nivel de anidamiento es', @@TRANCOUNT
COMMIT
TRAN TranExterna -- Reduce @@TRANCOUNT a 0.
--
Se lleva a cabo la transacción externa y todo lo que conlleva.
SELECT
'El nivel de anidamiento es', @@TRANCOUNT
SELECT
* FROM Test
Si no ponemos el nombre del
punto salvado con SAVE TRAN al hacer un ROLLBACK TRAN se deshace la transacción
más externa y @@TRANCOUNT se pone a 0.
Como podemos ver el uso de
transacciones no es complicado, e incluso las transacciones anidadas si
se tratan con cuidado son fáciles de manejar. Como siempre si hay
alguna duda la mejor fuente de ejemplos y soluciones son los BOL del SQL
Server.
César Manivesa
«
Atras |