Transações no SQL: Mantendo os dados íntegros e consistentes
Transação ou Transaction é uma única unidade de trabalho processada pelo Sistema de Gerenciamento de Banco de Dados (SGBD). Imagine que precisamos realizar em uma única transação duas operações de manipulação de dados (DML, do inglês Data Manipulation Language), como INSERT e UPDATE. Estas operações só podem se tornar permanentes no banco de dados se todas forem executadas com sucesso. Em caso de falhas em uma das duas é possível cancelar a transação, porém todas modificações realizadas durante a mesma serão descartadas, inclusive a que obtive sucesso. Assim, os dados permanecem íntegros e consistentes.
Problemas que podemos evitar com o uso de transações
Normalmente precisamos dos bancos de dados para armazenar os dados necessários para o funcionamento de uma empresa, ou de várias empresas, ou apenas dados pessoais. Pensando nisso, é muito importante mantermos esses dados seguros e consistentes. Outras vezes precisamos inserir novos dados, ou atualizar dados já existentes, ou ainda excluir esses dados para poder refletir o mundo real, porém alguém esqueceu de passar os dados corretos ou faltando partes dos mesmos, como vamos inserir essas informaçõe incompletas? Se inserirmos podemos não só deixar colocar dados incorretos e incompletos inviabilizando sua utilização como também podemos corromper as futuras informações que serão obtidas a partir desses dados armazenados, informações como relatórios comerciais, relatórios contábeis entre outros. Então precisamos sempre ter a certeza que todos os dados estão realmente em conformidade com o banco de dados e com o nosso mundo físico para só então salvá-los na base de dados, e é nesse ponto que entra o recurso de TRANSACTION que no português significa transações.
Transações implícitas
Na grande maioria dos SGBDs atuais as transações já acontecem de maneira implícita, cada comando que executamos por padrão já é uma transação isolada, quando executamos um comando de INSERT em uma tabela, a inserção só é realmente salva no banco de dados se todo o comando estiver correto, caso algum dos campos informados ou valores não estiverem exatamente como devem, será gerado um erro informando qual o problema, e nada é armazenado. Bem como as demais operações como UPDATE e DELETE também funcionam de forma semelhante. Assim, se os SGBDs já fazem transações de modo implícito, então é algo muito importante e devemos conhecer esse recurso tão poderoso para nos auxiliar no dia-a-dia e evitarmos transtornos.
Transações explícitas
Os SGBDs podem possuir alguma variação quanto às demais funcionalidades, porém a grande maioria segue o mesmo padrão quanto às transações explícitas. Bem as transações explícitas são aqueles que nós enquanto usuários determinamos, no caso informamos ao SGBD que desejamos que um conjunto de operações de INSERTs, UPDATEs, DELETEs sejam uma transação e só poderão se tornarem permanentes no banco de dados se todas forem executados com sucesso. Para isso precisamos indicar a partir de onde começa esse conjunto de comandos que estarão nessa transação, no SQL Server o comando é:
BEGIN TRANSACTION
No MySQL Server podemos utilizar esse mesmo comando acima ou então utilizar com o START, da seguinte forma:
START TRANSACTION
Ambos os comando indicam o começo da transação, e temos que informar os demais comandos de operações, e esses ficam no que chamamos de corpo da transação. Imagine que queremos inserir um novo registro numa tabela chamada produtos e também queremos excluir um outro produto que não existe mais no estoque, a nossa transação ficaria da seguinte forma:
BEGIN TRANSACTION
INSERT INTO produtos (CODIGO, NOME, PRECO) VALUES ('10', 'Suco de Laranja', 4.56);
DELETE FROM produtos WHERE CODIGO= 5;
Assim, nossa transação já foi iniciada, já está com as operações que queremos que sejam realizadas de única vez, porém ainda falta uma parte importante, como indicamos que queremos que essas operações sejam armazenadas no banco de dados? E para isso utilizamos o comando COMMIT, então nossa transação completa ficaria assim:
BEGIN TRANSACTION
INSERT INTO produtos (CODIGO, NOME, PRECO) VALUES ('10', 'Suco de Laranja', 4.56);
DELETE FROM produtos WHERE CODIGO= 5;
COMMIT;
Pronto, agora já podemos executar nossa transação e como todas as informações estão corretas, então será executada com sucesso e teremos um novo registro na nossa tabela de produtos e também não vai existir o produto com o código 5 na mesma tabela. Porém, imagine que deu algum erro, por exemplo, invertemos os campos dos VALUES do comando INSERT, trocamos a ordem no NOME e do PRECO dentro do VALUES desse jeito:
INSERT INTO produtos (CODIGO, NOME, PRECO) VALUES ('10', 4.56, 'Suco de Laranja);
Será gerado um erro, já que não podemos salvar um valor de ponto flutuante (4.56) em um campo que só aceita texto (VARCHAR), então não queremos que nada seja armazenado no banco de dados, já que a transação é uma unidade única, ou tudo é salvo no banco de dados ou nada, então poderíamos trocar o comando COMMIT pelo comando ROLLBACK, dessa maneira:
BEGIN TRANSACTION
INSERT INTO produtos (CODIGO, NOME, PRECO) VALUES ('10', 'Suco de Laranja', 4.56);
DELETE FROM produtos WHERE CODIGO= 5;
ROLLBACK;
Conclusão
Assim, nada foi salvo no banco de dados e nossos dados estão totalmente como estavam antes, conseguimos preservar a integridade e a consistência dos registros da nossa tabela de produtos, imagina que só poderíamos realizar o DELETE do um registro após inserir um outro registro antes, por alguma regra existente na empresa em que trabalhamos, e se as mudanças tivessem sido efetivadas no banco de dados, poderia ser simples de resolver não é? Nesse caso sim, foram apenas duas operações, mais de fossem 50 e só percebêssemos que alguma falou como faríamos? Seria uma dor de cabeça para consertar num era? Com a utilização de uma TRANSACTION isso será muito difícil de acontecer.
Sim, você pode está se perguntando, como automatizar esse processo de ter que alterarmos manualmente o COMMIT pelo ROLLBACK? Aqui na Alura temos a formação de SQL com MySQL Server da Oracle onde você pode se aprofundar nesse tema.