You are on page 1of 6

Transacciones en SQL Server

1. Introduccin
2. Sentencias para una transaccin
3. Un ejemplo
4. Transacciones anidadas
5. SA! T"A#
$. %i&lio'ra()a
Entre las habilidades de todo Sistema Gestor de Bases de Datos Relaciones tiene que estar la
de permitir al programador crear transacciones. El SQL Server nos permite trabajar con
transacciones de manera sencilla y eica!.
Introduccin
"na transacci#n es un conjunto de operaciones que van a ser tratadas como una $nica unidad.
Estas transacciones deben cumplir % propiedades undamentales com$nmente conocidas como
&'(D )atomicidad* coherencia* asilamiento y durabilidad+.
La transacci#n m,s simple en SQL Server es una $nica sentencia SQL. -or ejemplo una
sentencia como esta.
"-D&/E -roducts SE/ "nit-rice012 34ERE -roduct5ame 06'hai6
Es una transacci#n.
Esta es una transacci#n 7autocommit6* una transacci#n autocompletada.
'uando enviamos esta sentencia al SQL Server se escribe en el ichero de transacciones lo
que va a ocurrir y a continuaci#n reali!a los cambios necesarios en la base de datos. Si hay
alg$n tipo de problema al hacer esta operaci#n el SQL Server puede leer en el ichero de
transacciones lo que se estaba haciendo y si es necesario puede devolver la base de datos al
estado en el que se encontraba antes de recibir la sentencia.
-or supuesto este tipo de transacciones no requieren de nuestra intervenci#n puesto que el
sistema se encarga de todo. Sin embargo si hay que reali!ar varias operaciones y queremos
que sean tratadas como una unidad tenemos que crear esas transacciones de manera
e8pl9cita.
Sentencias para una transaccin
'omo dec9amos una transacci#n es un conjunto de operaciones tratadas como una sola. Este
conjunto de operaciones debe marcarse como transacci#n para que todas las operaciones que
la conorman tengan :8ito o todas racasen.
La sentencia que se utili!a para indicar el comien!o de una transacci#n es 7BEG(5 /R&56.
Si alguna de las operaciones de una transacci#n alla hay que deshacer la transacci#n en su
totalidad para volver al estado inicial en el que estaba la base de datos antes de empe!ar. Esto
se consigue con la sentencia 7R;LLB&'< /R&56.
Si todas las operaciones de una transacci#n se completan con :8ito hay que marcar el in de
una transacci#n para que la base de datos vuelva a estar en un estado consistente con la
sentencia 7';==(/ /R&56.
Un ejemplo
/rabajaremos con la base de datos 5orth>ind en nuestros ejemplos.
?amos a reali!ar una transacci#n que modiica el precio de dos productos de la base de datos.
"SE 5orth3ind
DE'L&RE @Error int
AADeclaramos una variable que utili!aremos para almacenar un posible c#digo de error
BEG(5 /R&5
AA(niciamos la transacci#n
"-D&/E -roducts SE/ "nit-rice012 34ERE -roduct5ame 06'hai6
AAEjecutamos la primera sentencia
SE/ @Error0@@ERR;R
AASi ocurre un error almacenamos su c#digo en @Error
AAy saltamos al tro!o de c#digo que deshara la transacci#n. Si* eso de ah9 es un
AAG;/;* el demonio de los programadores* pero no pasa nada por usarlo
AAcuando es necesario
(B )@ErrorCD2+ G;/; /ratarError
AASi la primera sentencia se ejecuta con :8ito* pasamos a la segunda
"-D&/E -roducts SE/ "nit-rice012 34ERE -roduct5ame06'hang6
SE/ @Error0@@ERR;R
AAE si hay un error hacemos como antes
(B )@ErrorCD2+ G;/; /ratarError
AASi llegamos hasta aqu9 es que los dos "-D&/E se han completado con
AA:8ito y podemos FguardarG la transacci#n en la base de datos
';==(/ /R&5
/ratarError.
AASi ha ocurrido alg$n error llegamos hasta aqu9
( @@ErrorCD2 /4E5
BEG(5
-R(5/ 74a ecorrido un error. &bortamos la transacci#n6
AASe lo comunicamos al usuario y deshacemos la transacci#n
AAtodo volver, a estar como si nada hubiera ocurrido
R;LLB&'< /R&5
E5D
'omo se puede ver para cada sentencia que se ejecuta miramos si se ha producido o no un
error* y si detectamos un error ejecutamos el bloque de c#digo que deshace la transacci#n.
4ay una interpretaci#n incorrecta en cuanto al uncionamiento de las transacciones que esta
bastante e8tendida. =ucha gente cree que si tenemos varias sentencias dentro de una
transacci#n y una de ellas alla* la transacci#n se aborta en su totalidad.
H5ada m,s lejos de la realidadI
Si tenemos dos sentencias dentro de una transacci#n.
"SE 5orth3ind
BEG(5 /R&5
"-D&/E -roducts SE/ "nit-rice012 34ERE -roduct5ame06'hang6
"-D&/E -roducts SE/ "nit-rice012 34ERE -roduct5ame06'hang6
';==(/ /R&5
Estas dos sentencias se ejecutar,n como una sola. Si por ejemplo en medio de la transacci#n
)despu:s del primer update y antes del segundo+ hay un corte de electricidad* cuando el SQL
Server se recupere se encontrar, en medio de una transacci#n y* o bien la termina o bien la
deshace* pero no se quedar, a medias.
El error est, en pensar que si la ejecuci#n de la primera sentencia da un error se cancelar, la
transacci#n. El SQL Server s#lo se preocupa de ejecutar las sentencias* no de averiguar si lo
hacen correctamente o si la l#gica de la transacci#n es correcta. Eso es cosa nuestra.
-or eso en el ejemplo que tenemos m,s arriba para cada sentencia de nuestro conjunto
averiguamos si se ha producido un error y si es as9 actuamos en consecuencia cancelando
toda la operaci#n.
Transacciones anidadas
;tra de las posibilidades que nos orece el SQL Server es utili!ar transacciones anidadas.
Esto quiere decir que podemos tener transacciones dentro de transacciones* es decir*
podemos empe!ar una nueva transacci#n sin haber terminado la anterior.
&sociada a esta idea de anidamiento e8iste una variable global @@/R&5';"5/ que tiene
valor 2 si no e8iste ning$n nivel de anidamiento* J si hay una transacci#n anidada* 1 si estamos
en el segundo nivel de anidamientoK y as9 sucesivamente.
La diicultad de trabajar con transacciones anidadas est, en el comportamiento que tienen
ahora las sentencias 7';==(/ /R&56 y 7R;LLB&'< /R&56
"*LL%A+, T"A#- Dentro de una transacci#n anidada esta sentencia deshace todas
las transacciones internas hasta la instrucci#n BEG(5 /R&5S&'/(;5 m,s e8terna.
+*..IT T"A#- Dentro de una transacci#n anidada esta sentencia $nicamente reduce
en J el valor de @@/R&5';"5/* pero no Finali!aG ninguna transacci#n ni FguardaG los
cambios. En el caso en el que @@/R&5';"5/0J )cuando estamos en la $ltima transacci#n+
';==(/ /R&5 hace que todas las modiicaciones eectuadas sobre los datos desde el inicio
de la transacci#n sean parte permanente de la base de datos* libera los recursos mantenidos
por la cone8i#n y reduce @@/R&5';"5/ a 2.
Qui!,s estos dos gr,icos nos ayuden a entender el comportamiento de estas
sentencias cuando hay varios niveles de anidamiento
+omportamiento del +*..IT T"A#
+omportamiento de "*LL%A+, T"A#
COMMIT TRAN
COMMIT TRAN
COMMIT TRAN
COMMIT TRAN
BEGIN TRAN
BEGIN TRAN
BEGIN TRAN
BEGIN TRAN
@@TRANCOUNT
0 1
2 3 4
'omo siempre un ejemplo es lo mejor para entender como unciona.
'RE&/E /&BLE /est )'olumna int+
G;
BEG(5 /R&5 /ranE8terna AA @@/R&5';"5/ ahora es J
SELE'/ 7El nivel de anidamiento es6* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )J+
BEG(5 /R&5 /ran(nternaJ AA @@/R&5';"5/ ahora es 1.
SELE'/ 7El nivel de anidamiento es6* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )1+
BEG(5 /R&5 /ran(nterna1 AA @@/R&5';"5/ ahora es L.
SELE'/ 7El nivel de anidamiento es6* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )L+
';==(/ /R&5 /ran(nterna1 AA Reduce @@/R&5';"5/ a 1.
AA -ero no se guarda nada en la base de datos.
SELE'/ 7El nivel de anidamiento es6* @@/R&5';"5/
';==(/ /R&5 /ran(nternaJ AA Reduce @@/R&5';"5/ a J.
AA -ero no se guarda nada en la base de datos.
SELE'/ 7El nivel de anidamiento es6* @@/R&5';"5/
';==(/ /R&5 /ranE8terna AA Reduce @@/R&5';"5/ a 2.
AA Se lleva a cabo la transacci#n e8terna y todo lo que conlleva.
SELE'/ 7El nivel de anidamiento es6* @@/R&5';"5/
SELE'/ M BR;= /est
-or cierto que lo de usar nombre para las transacciones es por claridad* puesto que ';==(/
/R&5 como ya hemos dicho solamente reduce en J el valor de @@/R&5';"5/.
?eamos ahora un ejemplo de transacci#n anidada con R;LLB&'< /R&5
BEG(5 /R&5 /ranE8terna AA @@/R&5';"5/ ahora es J
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )J+
BEG(5 /R&5 /ran(nternaJ AA @@/R&5';"5/ ahora es 1.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )1+
BEG(5 /R&5 /ran(nterna1 AA @@/R&5';"5/ ahora es L.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )L+
ROLLBACK TRAN
BEGIN TRAN
BEGIN TRAN
BEGIN TRAN
@@TRANCOUNT
BEGIN TRAN
0 1 2 3 4
R;LLB&'< /R&5 AA@@/R&5';"5/ es 2 y se deshace
AAla transacci#n e8terna y todas las internas
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
SELE'/ M BR;= /est
En este caso no se inserta nada puesto que el R;LLB&'< /R&5 deshace todas las
transacciones dentro de nuestro anidamiento hasta la transacci#n m,s e8terna y adem,s hace
@@/R&5';"5/02
OSupone este uncionamiento asim:trico del ';==(/ y del R;LLB&'< un problemaP
-ues 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. S&?E /R&5
SA! T"A#
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. -or supuesto nuestra
transacci#n debe continuar y terminar con un ';==(5 /R&5 )o los que hagan alta+ para que
todo se guarde o con un R;LLB&'< /R&5 para volver al estado previo al primer BEG(5
/R&5.
BEG(5 /R&5 /ranE8terna AA @@/R&5';"5/ ahora es J
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )J+
BEG(5 /R&5 /ran(nternaJ AA @@/R&5';"5/ ahora es 1.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )1+
S&?E /R&5 Guadada
BEG(5 /R&5 /ran(nterna1 AA @@/R&5';"5/ ahora es L.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
(5SER/ (5/; /est ?&L"ES )L+
R;LLB&'< /R&5 Guadada AA se deshace lo hecho el punto guardado.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
AA&hora podemos decidir si la transacci#n se lleva a cabo
AAo se deshace completamente
AA-ara deshacerla un R;LLB&'< bastar, como hemos visto
AA-ero para guardar la transacci#n hace alta reducir @@/R&5';"5/ a 2
';==(/ /R&5 /ran(nternaJ AA Reduce @@/R&5';"5/ a 1.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
';==(/ /R&5 /ran(nternaJ AA Reduce @@/R&5';"5/ a J.
AA -ero no se guarda nada en la base de datos.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
';==(/ /R&5 /ranE8terna AA Reduce @@/R&5';"5/ a 2.
AA Se lleva a cabo la transacci#n e8terna y todo lo que conlleva.
SELE'/ NEl nivel de anidamiento esN* @@/R&5';"5/
SELE'/ M BR;= /est
Si no ponemos el nombre del punto salvado con S&?E /R&5 al hacer un R;LLB&'< /R&5 se
deshace la transacci#n m,s e8terna y @@/R&5';"5/ se pone a 2.
'omo podemos ver el uso de transacciones no es complicado* e incluso las transacciones
anidadas si se tratan con cuidado son ,ciles de manejar. 'omo siempre si hay alguna duda la
mejor uente de ejemplos y soluciones son los B;L del SQL Server.
%i&lio'ra()a-
http.QQ>>>.microsot.comQsqlserver
B;L del SQL Server
&utor.
+esar .anivesa
http.QQsql.manivesa.com

You might also like