sql >> Base de Datos >  >> RDS >> Database

Comprender las transacciones en SQL

Una transacción en SQL es una unidad de ejecución que agrupa una o más tareas. Una transacción se considera exitosa si todas las tareas dentro de ella se ejecutan sin errores.

Sin embargo, si alguna de las tareas dentro de una transacción no se ejecuta, toda la transacción falla. Una transacción tiene solo dos resultados:exitosa o fallida.

Un escenario práctico

Considere un ejemplo práctico de un cajero automático (ATM). Vas al cajero automático y te pide tu tarjeta. Ejecuta una consulta para comprobar si la tarjeta es válida o no. A continuación, te pide tu código pin. De nuevo, ejecuta una consulta para que coincida con el código PIN. Luego, el cajero automático le pregunta la cantidad que desea retirar y usted ingresa la cantidad que desea. El cajero automático ejecuta otra consulta para deducir ese monto de su cuenta y luego le dispensa los fondos.

¿Qué pasa si el monto se deduce de su cuenta y luego el sistema falla debido a un corte de energía sin entregar los billetes?

Esto es problemático porque al cliente se le deducen los fondos sin haber recibido ningún dinero. Aquí es donde las transacciones pueden ser útiles.

En el caso de un bloqueo del sistema o cualquier otro error, todas las tareas dentro de la transacción se revierten. Por lo tanto, en el caso de un cajero automático, el monto se agregará nuevamente a su cuenta si no puede retirarlo por cualquier motivo.

¿Qué es una Transacción?

En su forma más simple, un cambio en una tabla de base de datos es una transacción. Por lo tanto, las declaraciones INSERT, UPDATE y DELETE son todas declaraciones de transacciones. Cuando escribe una consulta, se realiza una transacción. Sin embargo, esta transacción no se puede revertir. Veremos cómo se crean, confirman y revierten las transacciones a continuación, pero primero vamos a crear algunos datos ficticios con los que trabajar.

Preparación de los datos

Ejecute el siguiente script en su servidor de base de datos.

CREATE DATABASE schooldb

CREATE TABLE student
(
    id INT PRIMARY KEY,
    name VARCHAR(50) NOT NULL,
    gender VARCHAR(50) NOT NULL,
    age INT NOT NULL,
    total_score INT NOT NULL,
    
 )

INSERT INTO student 

VALUES (1, 'Jolly', 'Female', 20, 500), 
(2, 'Jon', 'Male', 22, 545), 
(3, 'Sara', 'Female', 25, 600), 
(4, 'Laura', 'Female', 18, 400), 
(5, 'Alan', 'Male', 20, 500)

La secuencia de comandos SQL anterior crea una base de datos schooldb. En esta base de datos, se crea una tabla estudiante y se agregan algunos datos ficticios a esa tabla.

Ejecución de consultas sin transacciones

Ejecutemos tres consultas estándar. No estamos usando transacciones en este momento.

INSERT INTO student 
VALUES (6, 'Suzi', 'Female', 25, 395)

UPDATE student
SET age = 'Six' WHERE id= 6

DELETE from student
WHERE id = 6

Aquí la primera consulta inserta un registro de estudiante en la base de datos. La segunda consulta actualiza la edad del estudiante y la tercera consulta elimina el registro recién insertado.

Si ejecuta el script anterior, verá que el registro se insertará en la base de datos y luego se producirá un error al ejecutar la segunda consulta.

Si observa la segunda consulta, estamos actualizando la edad almacenando un valor de cadena en la columna de edad que puede almacenar datos de tipo entero. Por lo tanto, se arrojará un error. Sin embargo, la primera consulta aún se completará con éxito. Esto significa que si selecciona todos los registros de la tabla de estudiantes, verá el registro recién insertado.

[id de tabla=23 /]

Puede ver que el registro con id=6 y el nombre 'Suzi' se ha insertado en la base de datos. Pero la edad no se pudo actualizar y la segunda consulta falló.

¿Qué pasa si no queremos esto? ¿Qué pasa si queremos estar seguros de que todas las consultas se ejecutan con éxito o ninguna de las consultas se ejecuta en absoluto? Aquí es donde las transacciones resultan útiles.

Ejecución de consultas con transacciones

Ahora ejecutemos las tres consultas anteriores dentro de una transacción.

Primero, veamos cómo crear y confirmar una transacción.

Crear una transacción

Para ejecutar una consulta/consultas como una transacción, simplemente incluya las consultas dentro de las palabras clave BEGIN TRANSACTION y COMMIT TRANSACTION. BEGIN TRANSACTION declara el inicio de una TRANSACCIÓN, mientras que COMMIT TRANSACTION indica que la transacción se ha completado.

Ejecutemos tres nuevas consultas en la base de datos que creamos anteriormente como una transacción. Agregaremos un nuevo registro para un nuevo estudiante con ID 7.

BEGIN TRANSACTION

	INSERT INTO student 
	VALUES (7, 'Jena', 'Female', 22, 456)

	UPDATE student
	SET age = 'Twenty Three' WHERE id= 7

	DELETE from student
	WHERE id = 7

COMMIT TRANSACTION

Cuando se ejecuta la transacción anterior, nuevamente se producirá un error en la segunda consulta, ya que nuevamente se almacena un valor de tipo cadena en la columna de edad que solo almacena datos de tipo entero.

Sin embargo, dado que el error ocurre dentro de una transacción, todas las consultas que se ejecutaron correctamente antes de que ocurriera este error se revertirán automáticamente. Por lo tanto, la primera consulta que inserta un nuevo registro de estudiante con id =7 y el nombre 'Jena' también se revertirá.

Ahora, si selecciona todos los registros de la tabla de estudiantes, verá que el nuevo registro de 'Jena' no se ha insertado.

Reversión manual de transacciones

Sabemos que si una consulta arroja un error dentro de una transacción, la transacción completa, incluidas todas las consultas ya ejecutadas, se revierte automáticamente. Sin embargo, también podemos revertir manualmente una transacción cuando queramos.

Para deshacer una transacción, se utiliza la palabra clave ROLLBACK seguida del nombre de la transacción. Para nombrar una transacción, se utiliza la siguiente sintaxis:

BEGIN TRANSACTION Transaction_name

Supongamos que queremos que nuestra tabla de estudiantes no tenga registros que contengan nombres de estudiantes duplicados. Agregaremos un registro para un nuevo estudiante. A continuación, comprobaremos si existe en la base de datos un alumno con un nombre idéntico al del nuevo alumno insertado. Si el estudiante con ese nombre aún no existe, confirmaremos nuestra transacción. Si existe un estudiante con ese nombre, revertiremos nuestra transacción. Haremos uso de sentencias condicionales en nuestra consulta.

Observe la siguiente transacción:

DECLARE @NameCount int

BEGIN TRANSACTION AddStudent

	INSERT INTO student 
	VALUES (8, 'Jacob', 'Male', 21, 600)

	SELECT @NameCount = COUNT(*) FROM student WHERE name = 'Jacob'

	IF @NameCount > 1
		BEGIN 
			ROLLBACK TRANSACTION AddStudent
			PRINT 'A student with this name already exists'
		END
	ELSE
		BEGIN
			COMMIT TRANSACTION AddStudent
			PRINT 'New record added successfully'
		END

Observe detenidamente la secuencia de comandos anterior. Muchas cosas están sucediendo aquí.

En la primera línea, creamos una variable SQL NameCount de tipo entero.

Luego, comenzamos una transacción llamada 'AddStudent'. Puede dar cualquier nombre a su transacción.

Dentro de la transacción, insertamos un nuevo registro para un estudiante con id =8 y nombre 'Jacob'.

Luego, usando la función de agregado COUNT, contamos el número de registros de estudiantes donde el nombre es 'Jacob' y almacenamos el resultado en la variable 'NameCount'.

Si el valor de la variable es mayor a 1, significa que ya existe un estudiante con el nombre de ‘Jacob’ en la base de datos. En ese caso, RETROCEDEMOS nuestra transacción e IMPRIMIMOS un mensaje en la pantalla que dice 'Ya existe un estudiante con este nombre'.

Si no, confirmamos nuestra transacción y mostramos el mensaje 'Nuevo registro agregado con éxito'.

Cuando ejecuta la transacción anterior por primera vez, no habrá un registro de estudiante con el nombre 'Jacob'. Por lo tanto, la transacción se confirmará y se imprimirá el siguiente mensaje:

Ahora intente ejecutar el siguiente script SQL en el servidor:

DECLARE @NameCount int

BEGIN TRANSACTION AddStudent

	INSERT INTO student 
	VALUES (9, 'Jacob', 'Male', 22, 400)

	SELECT @NameCount = COUNT(*) FROM student WHERE name = 'Jacob'

	IF @NameCount > 1
		BEGIN 
			ROLLBACK TRANSACTION AddStudent
			PRINT 'A student with this name already exists'
		END
	ELSE
		BEGIN
			COMMIT TRANSACTION
			PRINT 'New record added successfully'
		END

Aquí nuevamente, estamos insertando el registro del estudiante con id =9 y el nombre 'Jacob'. Dado que ya existe un registro de estudiante con el nombre 'Jacob' en la base de datos, la transacción se revertirá y se imprimirá el siguiente mensaje:

Enlaces útiles

  • Clases sobre transacciones SQL