0 calificaciones0% encontró este documento útil (0 votos)
79 vistas
4 - Variables, Flujos de Control y Transacciones
El documento describe las variables, operadores y estructuras de control en Transact-SQL. Las variables se declaran usando DECLARE y el prefijo @. Se pueden asignar valores a variables usando SET, SELECT o un cursor. Las estructuras de control incluyen IF, CASE, WHILE y GOTO.
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0 calificaciones0% encontró este documento útil (0 votos)
79 vistas
4 - Variables, Flujos de Control y Transacciones
El documento describe las variables, operadores y estructuras de control en Transact-SQL. Las variables se declaran usando DECLARE y el prefijo @. Se pueden asignar valores a variables usando SET, SELECT o un cursor. Las estructuras de control incluyen IF, CASE, WHILE y GOTO.
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 15
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC
MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES
BASES DE DATOS
Variables en Transact-SQL
Una variable es un valor identificado por un nombre (identificador) sobre el que podemos realizar modificaciones.
En Transact SQL los identificadores de variables deben comenzar por el caracter @, es decir, el nombre de una variable debe comenzar por @. Para declarar variables en Transact SQL debemos utilizar la palabra clave declare, seguido del identificador y tipo de datos de la variable.
-- Esto es un comentario de lnea simple /* Este es un comentario con varias lneas. Conjunto de Lneas. */ declare @nombre varchar(50)-- declare declara una variable -- @nombre es el identificador de la -- variable de tipo varchar set @nombre = 'www.devjoker.com' -- El signo = es un operador -- www.devjoker.com es un literal print @Nombre -- Imprime por pantalla el valor de @nombre. -- No diferencia maysculas ni minsculas
En Transact SQL podemos asignar valores a una variable de varias formas:
A travs de la instruccin set. Utilizando una sentencia SELECT. Realizando un FETCH de un cursor.
El siguiente ejemplo muestra como asignar una variable utilizando la instruccin SET.
DECLARE @nombre VARCHAR(100) -- La consulta debe devolver un nico registro SET @nombre = (SELECT nombre FROM CLIENTES WHERE ID = 1) PRINT @nombre
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
El siguiente ejemplo muestra como asignar variables utilizando una sentencia SELECT.
DECLARE @nombre VARCHAR(100), @apellido1 VARCHAR(100), @apellido2 VARCHAR(100) SELECT @nombre=nombre , @apellido1=Apellido1, @apellido2=Apellido2 FROM CLIENTES WHERE ID = 1
PRINT @nombre PRINT @apellido1 PRINT @apellido2
Un punto a tener en cuenta cuando asignamos variables de este modo, es que si la consulta SELECT devuelve ms de un registro, las variables quedarn asignadas con los valores de la ltima fila devuelta.
Por ltimo veamos como asignar variables a travs de un cursor.
DECLARE @nombre VARCHAR(100),@apellido1 VARCHAR(100),@apellido2 VARCHAR(100) DECLARE CDATOS CURSOR FOR SELECT nombre, Apellido1, Apellido2 FROM CLIENTES
OPEN CDATOS FETCH CDATOS INTO @nombre, @apellido1, @apellido2 WHILE (@@FETCH_STATUS = 0) BEGIN PRINT @nombre PRINT @apellido1 PRINT @apellido2 FETCH CDATOS INTO @nombre, @apellido1, @apellido2 END
CLOSE CDATOS DEALLOCATE CDATOS
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
Operadores en Transact SQL
Tipo de operador Operadores Operador de asignacin = Operadores aritmticos + (suma) - (resta) * (multiplicacin) / (divisin) ** (exponente) % (modulo) Operadores relacionales o de comparacin = (igual a) <> (distinto de) != (distinto de) < (menor que) > (mayor que) >= (mayor o igual a) <= (menor o igual a) !> (no mayor a) !< (no menor a) Operadores lgicos AND (y lgico) NOT (negacion) OR (o lgico) & (AND a nivel de bit) | (OR a nivel de bit) ^ (OR exclusivo a nivel de bit) Operador de concatenacin + Otros ALL (Devuelve TRUE si el conjunto completo de comparaciones es TRUE) ANY(Devuelve TRUE si cualquier elemento del conjunto de comparaciones es TRUE) BETWEEN (Devuelve TRUE si el operando est dentro del intervalo) EXISTS (TRUE si una subconsulta contiene filas) IN (TRUE si el operando est en la lista) LIKE (TRUE si el operando coincide con un patron) NOT (Invierte el valor de cualquier operador booleano) SOME(Devuelve TRUE si alguna de las comparaciones de un conjunto es TRUE)
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
Estructuras de Control en Transact SQL
Las estructuras de control dentro del lenguaje procedural de Transact SQL son:
Estructura IF Estructura CASE Bucle o ciclos WHILE Estructura GOTO
Estructura condicional IF La estructura condicional IF permite evaluar una expresin booleana (resultado VERDADERO - FALSO), y ejecutar las operaciones contenidas en el bloque formado por BEGIN / END.
IF (<expresion>) BEGIN ... END ELSE IF (<expresion>) BEGIN ... END ELSE BEGIN ... END
Ejemplo de la estructura condicional IF.
DECLARE @Web varchar(100), @diminutivo varchar(3)
SET @diminutivo = 'DJK'
IF @diminutivo = 'DJK' BEGIN PRINT 'www.devjoker.com' END ELSE BEGIN PRINT 'Otra Web (peor!)' END
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
La estructura IF admite el uso de subconsultas:
DECLARE @coPais int, @descripcion varchar(255)
set @coPais = 5 set @descripcion = 'Espaa'
IF EXISTS(SELECT * FROM PAISES WHERE CO_PAIS = @coPais) BEGIN UPDATE PAISES SET DESCRIPCION = @descripcion WHERE CO_PAIS = @coPais END
ELSE BEGIN INSERT INTO PAISES (CO_PAIS, DESCRIPCION) VALUES (@coPais, @descripcion) END
Estructura condicional CASE
La estructura condicional CASE permite evaluar una expresin y devolver un valor u otro.
La sintaxis general de case es:
CASE <expresion> WHEN <valor_expresion> THEN <valor_devuelto> WHEN <valor_expresion> THEN <valor_devuelto> ELSE <valor_devuelto> -- Valor por defecto END
SET @Web = (CASE @diminutivo WHEN 'DJK' THEN 'www.devjoker.com' WHEN 'ALM' THEN 'www.aleamedia.com' ELSE 'www.devjoker.com' END) PRINT @Web
Otra sintaxis de CASE nos permite evaluar diferentes expresiones:
CASE WHEN <expresion> = <valor_expresion> THEN <valor_devuelto> WHEN <expresion> = <valor_expresion> THEN <valor_devuelto> ELSE <valor_devuelto> -- Valor por defecto TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
END
El mismo ejemplo aplicando esta sintaxis:
DECLARE @Web varchar(100), @diminutivo varchar(3)
SET @diminutivo = 'DJK'
SET @Web = (CASE WHEN @diminutivo = 'DJK' THEN 'www.devjoker.com' WHEN @diminutivo = 'ALM' THEN 'www.aleamedia.com' ELSE 'www.devjoker.com' END) PRINT @Web
En CASE tambin se permite el uso de subconsultas
DECLARE @Web varchar(100), diminutivo varchar(3)
SET @diminutivo = 'DJK'
SET @Web = (CASE WHEN @diminutivo = 'DJK' THEN (SELECT web FROM WEBS WHERE id=1) WHEN @diminutivo = 'ALM' THEN (SELECT web FROM WEBS WHERE id=2) ELSE 'www.devjoker.com' END) PRINT @Web
Bucle o Ciclo WHILE
El bucle WHILE se repite mientras expresin se evale como verdadero.
WHILE Es el nico tipo de bucle del que dispone Transact SQL.
WHILE <expresion> BEGIN ... END
Ejemplo:
DECLARE @contador int
SET @contador = 0
WHILE (@contador < 100) BEGIN SET @contador = @contador + 1
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
PRINT 'Iteracion del bucle ' + cast(@contador AS varchar) END
Podemos saltar a la siguiente iteracin del bucle utilizando CONTINUE.
DECLARE @contador int
SET @contador = 0
WHILE (@contador < 100) BEGIN SET @contador = @contador + 1 IF (@contador % 2 = 0) CONTINUE PRINT 'Iteracion del bucle ' + cast(@contador AS varchar) END
En este caso solo imprimir la lnea de texto cuando el valor de @contador sea impar
Con Break el ciclo se interrumpir:
DECLARE @contador int
SET @contador = 0 WHILE (1 = 1) BEGIN SET @contador = @contador + 1 IF (@contador % 50 = 0) BREAK PRINT 'Iteracion del bucle ' + cast(@contador AS varchar) END
Cuando el valor de @contador llegue a 50, el ciclo se interrumpir y terminar
Tambin podemos utilizar el bucle WHILE conjuntamente con subconsultas.
DECLARE @coRecibo int WHILE EXISTS (SELECT * FROM RECIBOS WHERE PENDIENTE = 'S') -- Ojo, la subconsulta se ejecuta -- una vez por cada iteracion -- del bucle!
BEGIN SET @coRecibo = (SELECT TOP 1 CO_RECIBO FROM RECIBOS WHERE PENDIENTE = 'S')
UPDATE RECIBOS SET PENDIENTE = 'N' WHERE CO_RECIBO = @coRecibo END
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
Estructura GOTO
La sentencia goto nos permite desviar el flujo de ejecucin hacia una etiqueta. Fu muy utilizada en versiones anteriores de SQL Server conjuntamente con la variable de sistema @@ERROR para el control de errores.
Actualmente, se desaconseja el uso GOTO, recomendndose el uso de TRY - CATCH para la gestin de errores.
DECLARE @divisor int, @dividendo int, @resultado int
SET @dividendo = 100 SET @divisor = 0 SET @resultado = @dividendo/@divisor
IF @@ERROR > 0 GOTO error
PRINT 'No hay error' RETURN error: PRINT 'Se ha producido una division por cero'
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
Transacciones
Una transaccin es un conjunto de operaciones Transact SQL que se ejecutan como un nico bloque, es decir, si falla una operacin Transact SQL fallan todas.
Si una transaccin tiene xito, todas las modificaciones de los datos realizadas durante la transaccin se confirman y se convierten en una parte permanente de la base de datos. Si una transaccin encuentra errores y debe cancelarse o revertirse, se borran todas las modificaciones de los datos.
El ejemplo clsico de transaccin es una transferencia bancaria, en la que quitamos saldo a una cuenta y lo aadimos en otra. Si no somos capaces de abonar el dinero en la cuenta de destino, no debemos quitarlo de la cuenta de origen.
SQL Server funciona por defecto con Transacciones de confirmacin automtica, es decir, cada instruccin individual es una transaccin y se confirma automticamente.
Sobre el ejemplo anterior de la transferencia bancaria, un script debera realizar algo parecido a lo siguiente:
DECLARE @importe DECIMAL(18,2), @CuentaOrigen VARCHAR(12), @CuentaDestino VARCHAR(12) /* Asignamos el importe de la transferencia * y las cuentas de origen y destino */ SET @importe = 50 SET @CuentaOrigen = '200700000001' SET @CuentaDestino = '200700000002'
/* Descontamos el importe de la cuenta origen */ UPDATE CUENTAS SET SALDO = SALDO - @importe WHERE NUMCUENTA = @CuentaOrigen
/* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO + @importe, SALDO, @importe, getdate() FROM CUENTAS WHERE NUMCUENTA = @CuentaOrigen
/* Incrementamos el importe de la cuenta destino */ UPDATE CUENTAS SET SALDO = SALDO + @importe WHERE NUMCUENTA = @CuentaDestino
/* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO - @importe, SALDO, @importe, getdate() FROM CUENTAS TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
WHERE NUMCUENTA = @CuentaDestino
Esta forma de actuar seria errnea, ya que cada instruccin se ejecutara y confirmara de forma independiente, por lo que un error dejara los datos errneos en la base de datos ( y ese es el peor error que nos podemos encontrar! )
Transacciones implcitas y explicitas
Para agrupar varias sentencias Transact SQL en una nica transaccin, disponemos de los siguientes mtodos:
Transacciones explcitas Cada transaccin se inicia explcitamente con la instruccin BEGIN TRANSACTION y se termina explcitamente con una instruccin COMMIT o ROLLBACK. Transacciones implcitas Se inicia automticamente una nueva transaccin cuando se ejecuta una instruccin que realiza modificaciones en los datos, pero cada transaccin se completa explcitamente con una instruccin COMMIT o ROLLBACK.
Para activar-desactivar el modo de transacciones implcitas debemos ejecutar la siguiente instruccin.
--Activamos el modo de transacciones implcitas SET IMPLICIT_TRANSACTIONS ON --Desactivamos el modo de transacciones implcitas SET IMPLICIT_TRANSACTIONS OFF
Cuando la opcin ANSI_DEFAULTS est establecida en ON, IMPLICIT_TRANSACTIONS tambin se establece en ON.
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
El siguiente ejemplo muestra el script anterior haciendo uso de transacciones explicitas.
/* Asignamos el importe de la transferencia * y las cuentas de origen y destino */ SET @importe = 50 SET @CuentaOrigen = '200700000002' SET @CuentaDestino = '200700000001'
BEGIN TRANSACTION -- O solo BEGIN TRAN BEGIN TRY /* Descontamos el importe de la cuenta origen */ UPDATE CUENTAS SET SALDO = SALDO - @importe WHERE NUMCUENTA = @CuentaOrigen
/* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO + @importe, SALDO, @importe, getdate() FROM CUENTAS WHERE NUMCUENTA = @CuentaOrigen
/* Incrementamos el importe de la cuenta destino */ UPDATE CUENTAS SET SALDO = SALDO + @importe WHERE NUMCUENTA = @CuentaDestino
/* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO - @importe, SALDO, @importe, getdate() FROM CUENTAS WHERE NUMCUENTA = @CuentaDestino
/* Confirmamos la transaccion*/ COMMIT TRANSACTION -- O solo COMMIT
END TRY BEGIN CATCH /* Hay un error, deshacemos los cambios*/ ROLLBACK TRANSACTION -- O solo ROLLBACK PRINT 'Se ha producido un error!' END CATCH
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
El siguiente ejemplo muestra el mismo script con transacciones implicitas.
/* Asignamos el importe de la transferencia * y las cuentas de origen y destino */ SET @importe = 50 SET @CuentaOrigen = '200700000002' SET @CuentaDestino = '200700000001'
BEGIN TRY /* Descontamos el importe de la cuenta origen */ UPDATE CUENTAS SET SALDO = SALDO - @importe WHERE NUMCUENTA = @CuentaOrigen
/* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO + @importe, SALDO, @importe, getdate() FROM CUENTAS WHERE NUMCUENTA = @CuentaOrigen
/* Incrementamos el importe de la cuenta destino */ UPDATE CUENTAS SET SALDO = SALDO + @importe WHERE NUMCUENTA = @CuentaDestino
/* Registramos el movimiento */ INSERT INTO MOVIMIENTOS (IDCUENTA, SALDO_ANTERIOR, SALDO_POSTERIOR, IMPORTE, FXMOVIMIENTO) SELECT IDCUENTA, SALDO - @importe, SALDO, @importe, getdate() FROM CUENTAS WHERE NUMCUENTA = @CuentaDestino
/* Confirmamos la transaccion*/ COMMIT TRANSACTION -- O solo COMMIT END TRY BEGIN CATCH /* Hay un error, deshacemos los cambios*/ ROLLBACK TRANSACTION -- O solo ROLLBACK PRINT 'Se ha producido un error!' END CATCH
La transaccin sigue activa hasta que emita una instruccin COMMIT o ROLLBACK.
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
Una vez que la primera transaccin se ha confirmado o revertido, se inicia automticamente una nueva transaccin la siguiente vez que la conexin ejecuta una instruccin para modificar datos.
La conexin contina generando transacciones implcitas hasta que se desactiva el modo de transacciones implcitas.
Podemos verificar el nmero de transacciones activas a travs de @@TRANCOUNT.
SET IMPLICIT_TRANSACTIONS ON
BEGIN TRY UPDATE CUENTAS SET FXALTA = FXALTA - 1
PRINT @@TRANCOUNT COMMIT END TRY
BEGIN CATCH ROLLBACK PRINT 'Error' END CATCH
Otro punto a tener en cuenta cuando trabajamos con transacciones son los bloqueos y el nivel de aislamiento.
Un bloqueo diremos que un bloqueo se produce cuando un usuario modifica o lee datos en una transaccin.
Por ejemplo, imaginemos que estamos actualizando una "factura" de estado "pendiente" a estado "pagado", durante el tiempo que dura la transaccin (antes de hacer COMMIT o ROLLBACK), si otro usuario quiere ver el estado de la "factura" ... qu estado mostramos? Los datos estn cambiando!
Si devolvemos "pendiente" no sera correcto, ya que el estado ha cambiado a "pagado", pero si devolvemos "pagado" tampoco es correcto, ya que la transaccin podra hacer ROLLBACK y abramos efectuado una lectura incorrecta.
SQL Server bloquea la fila (en el mejor de los casos) e impide el acceso a los datos afectados por la transaccin, como consecuencia el resto de usuarios concurrentes se quedan "bloqueados", sin posibilidad siquiera de leer los datos.
Para controlar como afectan los bloqueos a las transacciones, podemos modificar el nivel de aislamiento de las transacciones a travs de la instruccin SET TRANSACTION ISOLATION LEVEL. Con esta instruccin controlamos como interpreta la transaccin los bloqueos existentes y como genera nuevos bloqueos con sus operaciones de lectura/escritura.
La sintaxis es la siguiente:
SET TRANSACTION ISOLATION LEVEL <opcion>
TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
Donde <opcion> puede tomar estos valores:
READ COMMITTED - La transaccin no puede leer datos modificados por otras transacciones. Permite a otras transacciones puedan modificar los datos que se han ledo. Esta opcin es la predeterminada para SQL Server (incluido 2005). READ UNCOMMITTED - La transaccin es capaz de leer los datos modificados por otras transacciones pero que an no han sido confirmadas (pendientes de COMMIT). REPEATABLE READ - La transaccin no puede leer datos modificados por otras transacciones y otras transacciones no pueden modificar los datos que se han ledo. SERIALIZABLE - Las instrucciones no pueden leer datos que hayan sido modificados, pero an no confirmados, por otras transacciones y ninguna otra transaccin puede modificar los datos ledos por la transaccin actual ni insertar filas nuevas con valores de clave que pudieran estar incluidos en el intervalo de claves hasta que la transaccin actual finalice. SNAPSHOT - Activa el versionado de fila. Las instrucciones que se ejecuten en la transaccin no vern las modificaciones de datos efectuadas por otras transacciones, en su lugar reciben una "copia coherente" de cmo estaban los datos al comienzo de la transaccin. De este modo actan otros gestores de bases de datos muy populares, como por ejemplo, ORACLE.
Para activar la opcin ALLOW_SNAPSHOT_ISOLATION con la siguiente instruccin:
ALTER DATABASE MyDatabase SET ALLOW_SNAPSHOT_ISOLATION ON
Transacciones anidadas.
Cuando anidamos varias transacciones la instruccin COMMIT afectar a la ltima transaccin abierta, pero ROLLBACK afectar a todas las transacciones abiertas.
Un hecho a tener en cuenta, es que, si hacemos ROLLBACK de la transaccin superior se desharn tambin los cambios de todas las transacciones internas, aunque hayamos realizado COMMIT de ellas.
BEGIN TRAN
UPDATE EMPLEADOS SET NOMBRE = 'Devjoker' WHERE ID=101
BEGIN TRAN
UPDATE EMPLEADOS SET APELLIDO1 = 'Devjoker.COM' WHERE ID=101
-- Este COMMIT solo afecta a la segunda transaccion. COMMIT
-- Este ROLLBACK afecta a las dos transacciones. ROLLBACK TECNOLGICO DE ESTUDIOS SUPERIORES DE ECATEPEC MAESTRA EN INGENIERA EN SISTEMAS COMPUTACIONALES BASES DE DATOS
Una consideracin a tener en cuenta cuando trabajamos con transacciones anidadas es la posibilidad de utilizar puntos de guardado o SAVEPOINTs.
Puntos de recuperacin (SavePoint).
Los puntos de recuperacin (SavePoints) permiten manejar las transacciones por pasos, pudiendo hacer rollbacks hasta un punto marcado por el savepoint y no por toda la transaccin.
El siguiente ejemplo muestra como trabajar con puntos de recuperacin.
BEGIN TRAN
UPDATE EMPLEADOS SET NOMBRE = 'Devjoker' WHERE ID=101
UPDATE EMPLEADOS SET APELLIDO1 = 'Devjoker.COM' WHERE ID=101
SAVE TRANSACTION P1 -- Guardamos la transaccion (Savepoint)
UPDATE EMPLEADOS SET APELLIDO1 = 'Otra cosa!' WHERE ID=101
-- Este ROLLBACK afecta solo a las instrucciones -- posteriores al savepoint P1. ROLLBACK TRANSACTION P1