Database
 sql >> Base de Dados >  >> RDS >> Database

Entendendo as transações no SQL

Uma transação em SQL é uma unidade de execução que agrupa uma ou mais tarefas. Uma transação é considerada bem-sucedida se todas as tarefas dentro dela forem executadas sem erros.

No entanto, se qualquer uma das tarefas em uma transação não for executada, toda a transação falhará. Uma transação tem apenas dois resultados:bem-sucedida ou com falha.

Um cenário prático

Considere um exemplo prático de um ATM (Automated Teller Machine). Você vai ao caixa eletrônico e ele pede seu cartão. Ele executa uma consulta para verificar se o cartão é válido ou não. Em seguida, ele solicita seu código PIN. Novamente, ele executa uma consulta para corresponder ao código PIN. O caixa eletrônico solicita o valor que você deseja sacar e você insere o valor desejado. O caixa eletrônico executa outra consulta para deduzir esse valor da sua conta e, em seguida, libera os fundos para você.

E se o valor for descontado da sua conta e o sistema travar devido a uma falha de energia sem dispensar as notas?

Isso é problemático porque o cliente tem os fundos deduzidos sem ter recebido nenhum dinheiro. É aqui que as transações podem ser úteis.

No caso de uma falha do sistema ou qualquer outro erro, todas as tarefas dentro da transação são revertidas. Portanto, no caso de um caixa eletrônico, o valor será adicionado de volta à sua conta se você não conseguir sacar por qualquer motivo.

O que é uma transação?

Em sua forma mais simples, uma mudança em uma tabela de banco de dados é uma transação. Portanto, as instruções INSERT, UPDATE e DELETE são todas instruções de transação. Quando você escreve uma consulta, uma transação é executada. No entanto, esta transação não pode ser revertida. Veremos como as transações são criadas, confirmadas e revertidas abaixo, mas primeiro vamos criar alguns dados fictícios para trabalhar.

Preparando os dados

Execute o script a seguir em seu servidor de banco de dados.

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)

O script SQL acima cria um banco de dados schooldb. Nesse banco de dados, uma tabela student é criada e alguns dados fictícios são adicionados a essa tabela.

Executando consultas sem transações

Vamos executar três consultas padrão. Não estamos usando transações no momento.

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

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

DELETE from student
WHERE id = 6

Aqui a primeira consulta insere um registro de aluno no banco de dados. A segunda consulta atualiza a idade do aluno e a terceira consulta exclui o registro recém-inserido.

Se você executar o script acima, verá que o registro será inserido no banco de dados e então ocorrerá um erro ao executar a segunda consulta.


Se você observar a segunda consulta, estamos atualizando a idade armazenando um valor de string na coluna de idade que pode armazenar dados do tipo inteiro. Portanto, um erro será lançado. No entanto, a primeira consulta ainda será concluída com êxito. Isso significa que, se você selecionar todos os registros da tabela de alunos, verá o registro recém-inserido.

[ID da tabela=23 /]

Você pode ver que o registro com id=6 e nome ‘Suzi’ foi inserido no banco de dados. Mas a idade não pôde ser atualizada e a segunda consulta falhou.

E se não quisermos isso? E se quisermos ter certeza de que todas as consultas são executadas com êxito ou nenhuma das consultas é executada? É aqui que as transações são úteis.

Executando consultas com transações

Agora vamos executar as três consultas acima dentro de uma transação.

Primeiro, vamos ver como criar e confirmar uma transação.

Criando uma transação

Para executar uma consulta/consultas como uma transação, basta agrupar as consultas nas palavras-chave BEGIN TRANSACTION e COMMIT TRANSACTION. O BEGIN TRANSACTION declara o início de uma TRANSACTION enquanto o COMMIT TRANSACTION indica que a transação foi concluída.

Vamos executar três novas consultas no banco de dados que criamos anteriormente como uma transação. Estaremos adicionando um novo registro para um novo aluno com 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

Quando a transação acima for executada, novamente ocorrerá um erro na segunda consulta, pois novamente um valor do tipo string está sendo armazenado na coluna age que armazena apenas dados do tipo inteiro.

No entanto, como o erro ocorre dentro de uma transação, todas as consultas executadas com sucesso antes da ocorrência desse erro serão automaticamente revertidas. Portanto, a primeira consulta que insere um novo registro de aluno com id =7 e nome ‘Jena’ também será revertida.

Agora, se você selecionar todos os registros da tabela de alunos, verá que o novo registro para ‘Jena’ não foi inserido.

Reversão de transação manual

Sabemos que se uma consulta gerar um erro em uma transação, toda a transação, incluindo todas as consultas já executadas, será automaticamente revertida. No entanto, também podemos reverter manualmente uma transação sempre que quisermos.

Para reverter uma transação, a palavra-chave ROLLBACK é usada seguida do nome da transação. Para nomear uma transação, a seguinte sintaxe é usada:

BEGIN TRANSACTION Transaction_name

Suponha que queremos que nossa tabela de alunos não tenha registros contendo nomes de alunos duplicados. Adicionaremos um registro para um novo aluno. Em seguida, verificaremos se existe no banco de dados um aluno com nome idêntico ao nome do aluno recém-inserido. Se o aluno com esse nome ainda não existir, confirmaremos nossa transação. Se existir um aluno com esse nome, reverteremos nossa transação. Faremos uso de declarações condicionais em nossa consulta.

Dê uma olhada na seguinte transação:

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

Dê uma olhada cuidadosa no script acima. Muitas coisas estão acontecendo aqui.

Na primeira linha, criamos uma variável SQL do tipo inteiro NameCount.

Em seguida, iniciamos uma transação chamada 'AddStudent'. Você pode dar qualquer nome à sua transação.

Dentro da transação, inserimos um novo registro para um aluno com id =8 e nome ‘Jacob’.

A seguir, usando a função agregada COUNT contamos o número de registros de alunos onde o nome é ‘Jacob’ e armazenamos o resultado na variável ‘NameCount’.

Se o valor da variável for maior que 1, significa que um aluno com o nome ‘Jacob’ já existe no banco de dados. Nesse caso, ROLLBACK nossa transação e IMPRIMIR uma mensagem na tela que ‘Já existe um aluno com este nome’.

Caso contrário, confirmamos nossa transação e exibimos a mensagem 'Novo registro adicionado com sucesso'.

Quando você executar a transação acima pela primeira vez, não haverá um registro de aluno com o nome 'Jacob'. Portanto, a transação será confirmada e a seguinte mensagem será impressa:



Agora tente executar o seguinte script SQL no 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

Aqui novamente, estamos inserindo o registro do aluno com id =9 e nome ‘Jacob’. Como já existe um cadastro de aluno com o nome ‘Jacob’ no banco de dados, a transação será revertida e a seguinte mensagem será impressa:


Links úteis

  • Aulas sobre transações SQL