Banco de Dados

6 out, 2010

Tipo de transações no SQL Server

Publicidade

Em ambientes multi-usuários,
existem operações que precisam ser serializadas, ou seja, colocadas em
fila para que sejam executadas “uma a uma”, não permitindo tarefas em paralelo. Essas operações são amparadas por um conceito muito forte em bancos de dados relacionais denominado Transação, cujo objetivo
é agrupar uma sequência de comandos que precisam ser tratados como um
bloco único e invisível, para que se mantenham a integridade e a
consistência dos dados.

O SQL Server fornece três maneiras de tratar transações, que
podemos definir dentro de uma conexão. Essas três maneiras são:

  • Transações de autoconfirmação
  • Transações explícitas
  • Transações implícitas

Vamos explicar cada uma na prática. Para isso, em um banco de
dados qualquer, crie a seguinte tabela:

CREATE TABLE OBJETO (

ID INT NOT NULL PRIMARY KEY,

COLUNA1 VARCHAR(20) NOT NULL,

COLUNA2 VARCHAR(20) NULL);

Com a tabela criada, vamos às transações.

Transações de autoconfirmação

Para explicar esse modelo, vamos à prática. Faça os 3 inserts
abaixo:

INSERT INTO OBJETO VALUES (1, 'Primeira coluna', 'Primeira coluna');

INSERT INTO OBJETO VALUES (2, null, 'Segunda coluna');

INSERT INTO OBJETO VALUES (3, 'Terceira coluna', 'Terceira coluna');

Após a execução, recebemos a seguinte mensagem:

(1 row(s) affected)

Msg 515, Level 16, State 2, Line 3

Cannot insert the value NULL into column 'COLUNA1', table 'QUESTIONARIO.dbo.OBJETO'; column does not allow nulls. INSERT fails.

The statement has been terminated.



(1 row(s) affected)

A mensagem é porque a COLUNA1 da tabela OBJETO não aceita
valor NULL.

Agora vamos executar um SELECT simples na tabela OBJETO. Podemos
verificar que os inserts 1 e 3 foram
executados. Isso significa que quando o SQL Server usa transações de
autoconfirmação, cada instrução é uma transação por si só. Quando uma instrução
produz um erro (como no insert 2), automaticamente a instrução é revertida,
senão ela é confirmada.

Transações explícitas

Nesse tipo, o desenvolvedor define onde a
transação é inicializada e onde ela é finalizada ou revertida. Para isso,
utilizaremos as seguintes instruções:

  • Begin Transaction: para iniciar uma transação;
  • Commit Transaction: para confirmar uma
    transação;
  • Rollback Transaction: para reverter uma
    transação.

A palavra TRANSACTION pode ser abreviada para TRAN. Vamos ao
exemplo: para isso, peço que você exclua todos os registros da tabela OBJETO.

Agora vamos utilizar o código da seguinte forma:

BEGIN TRAN

INSERT INTO OBJETO VALUES (1, 'Primeira coluna', 'Primeira coluna');

INSERT INTO OBJETO VALUES (2, null, 'Segunda coluna');

INSERT INTO OBJETO VALUES (3, 'Terceira coluna', 'Terceira coluna');

COMMIT TRAN

Vamos executar o código, e o que acontece? Você irá receber a
mesma mensagem de erro do exemplo anterior e, ao executar uma consulta na tabela
OBJETO, irá obter o mesmo resultado. Então, o que mudou? Lembre-se: é
responsabilidade do desenvolver determinar se a transação deve ser revertida.
No exemplo acima, não fizemos nenhum tratamento para que a instrução fosse revertida no caso de algum erro.

Melhorando nossa rotina. Exclua novamente todos os registro
da tabela OBJETO e vamos agora alterar nosso exemplo conforme abaixo:

BEGIN TRY

BEGIN TRAN

INSERT INTO OBJETO VALUES (1, 'Primeira coluna', 'Primeira coluna');

INSERT INTO OBJETO VALUES (2, null, 'Segunda coluna');

INSERT INTO OBJETO VALUES (3, 'Terceira coluna', 'Terceira coluna');

COMMIT TRAN;

END TRY

BEGIN CATCH

SELECT ERROR_NUMBER() AS "ERROR_NUMBER",

ERROR_SEVERITY() AS "ERROR_SEVERITY",

ERROR_STATE() AS "ERROR_STATE",

ERROR_PROCEDURE() AS "ERROR_PROCEDURE",

ERROR_LINE() AS "ERROR_LINE",

ERROR_MESSAGE() AS "ERROR_MESSAGE"

RAISERROR('Erro na transação', 14, 1)

ROLLBACK TRAN;

END CATCH;

Nesse exemplo estamos utilizando a rotina de tratamento de
erro TRY e CATCH.

Execute a rotina acima e veja que nenhum registro será incluído
na tabela OBJETO, ou seja, a reversão da instrução foi executada com
sucesso. Para melhorar nosso tratamento de erro, adicionei ao CATCH uma consulta
que traga mais informações sobre o erro e uma mensagem de erro.

Transações implícitas

Esse terceiro modo de transação no SQL Server inicia uma
transação se nenhuma já tiver sido inicializada, mas o COMMIT ou
o ROLLBACK deve ser definido pelo desenvolvedor.

Para usar esse tipo de transação, precisamos ativá-la no SQL
Server usando o código abaixo:

SET IMPLICIT_TRANSACTIONS ON;

Agora execute a instrução abaixo para verificar quantas
transações em aberto existem:

SELECT @@TRANCOUNT

Você deve ter como resultado o valor 0.

Crie uma tabela simples e execute o @@TRANCOUNT novamente:

CREATE TABLE TESTE (ID INT PRIMARY KEY);

SELECT @@TRANCOUNT;

O resultado agora é 1, uma transação foi inicializada. E se
executamos um insert simples nessa tabela?

INSERT INTO TESTE VALUES (5);

SELECT * FROM TESTE;

SELECT @@TRANCOUNT;

A instrução insert foi executada, porém continuamos a ter
uma única transação.

Para finalizar, vamos executar um ROLLBACK:

ROLLBACK TRAN;

SELECT @@TRANCOUNT;

Pronto, nossa transação foi revertida. Se você quiser confirmar, execute um SELECT na tabela TESTE. O que aconteceu? Uma mensagem de erro
informando que a tabela não existe é exibida, ou seja, nosso ROLLBACK reverteu
tudo, desde o insert à criação da tabela.

Para finalizar, vamos desativar as transações implícitas:

SET IMPLICIT_TRANSACTIONS OFF;

Chegamos ao fim deste artigo, porém não do assunto! Existem
mais informações sobre transações que você pode pesquisar como transações
aninhadas, níveis de isolamento de uma transação, entre outros.

Obrigado, pessoal, e até a próxima.