Demétrio's profileDemétrio Silva - Sql Ser...BlogListsNetworkMore Tools Help

Blog


    September 08

    Situações onde o bloco catch não é executado

    Galera,

     

    Hoje vou falar sobre um assunto bem interessante: Situações onde o bloco catch não é executado. Essa semana eu estava lendo sobre este assunto e achei útil mostrar em que situações o bloco catch não é executado.

     

    Abaixo temos alguns exemplos:

     

    KILL ou Timeout do comando

     

    Imagine ter um código onde você realiza vários updates em uma ou várias tabelas dentro de um bloco begin try e, caso exista algum problema durante a atualização, a transação deve ser revertida e a linha e mensagem de erro devem ser logadas em uma tabela destinada ao log de erros.

     

    Bom, vamos criar nossa base de dados e as tabelas conforme script abaixo:

    --CRIA E COLOCA EM USO O DATABASE

    CREATE DATABASE DB_TESTE

    GO

     

    USE DB_TESTE

    GO

     

    --CRIA TABELA QUE VAI ARMAZENAR OS ERROS OCORRIDOS

    CREATE TABLE TB_ERROR(ELINE INT ,  EMESSAGE nvarchar(2048))

     

    --CRIA A TABELA PARA TESTAR O UPDATE

    CREATE TABLE CLIENTE ( ID INT, NOME VARCHAR(10), STATUS CHAR(1))

    GO

     

    --ADICIONA UMA CHECK PARA O CAMPO STATUS ( A = ATIVO, I = INATIVO )

    ALTER TABLE CLIENTE  WITH CHECK ADD  CONSTRAINT CK_STATUS CHECK ( STATUS = 'A' OR STATUS = 'I')

    GO

     

    --POPULA A TABELA

    INSERT INTO CLIENTE( ID, NOME, STATUS ) VALUES ( 1, 'DEMÉTRIO', 'A' )

    INSERT INTO CLIENTE( ID, NOME, STATUS ) VALUES ( 2, 'MARIA', 'A' )

    INSERT INTO CLIENTE( ID, NOME, STATUS ) VALUES ( 3, 'JOSÉ', 'A' )

    INSERT INTO CLIENTE( ID, NOME, STATUS ) VALUES ( 4, 'JOÃO', 'I' )

    INSERT INTO CLIENTE( ID, NOME, STATUS ) VALUES ( 5, 'PEDRO', 'I' )

     

    --VERIFICA OS DADOS INSERIDOS

    SELECT * FROM CLIENTE

    Bom, conforme podemos verificar, o script abaixo realiza dois updates na tabela, sendo que o segundo gera um erro. Ao capturar o erro, o bloco catch realiza o rollback da transação e insere a linha e mensagem de erro na tabela TB_ERROR.

    BEGIN TRY

         

          BEGIN TRAN

               

                --ATUALIZA TODOS OS DADOS DO CAMPO NOME DA TABELA

                UPDATE CLIENTE SET NOME += '_'

               

                --ATUALIZA TODOS OS STATUS PARA 'L', VAI GERAR ERRO POR CAUSA DA CHECK CONSTRAINT

                UPDATE CLIENTE SET STATUS = 'L'

         

          COMMIT

         

    END TRY

    BEGIN CATCH

     

          --SE HOUVE ERRO, REVERTE A TRANSAÇÃO E LOGA O ERRO NA TABELA

          IF @@TRANCOUNT > 0

                ROLLBACK

     

          INSERT INTO TB_ERROR ( ELINE, EMESSAGE )

          SELECT

                ERROR_LINE(),

                ERROR_MESSAGE()        

               

    END CATCH

     

     

    Como podemos verificar no select abaixo, o primeiro update é revertido e um registro é gravado na tabela de log.

    SELECT * FROM CLIENTE

    SELECT * FROM TB_ERROR

    --LIMPA O LOG DE ERROS

    DELETE TB_ERROR

    Até agora sem problemas. Mas, e se alguém executar um kill ou mesmo existir um timeout na conexão que está executando o update?

    A transação é revertida, não através do rollback contido no bloco catch, mas sim porque esse é procedimento executado quando utilizamos um kill contra algum processo. No entanto, note que o insert na tabela de log não é executado, ou seja, isso é uma prova que o bloco catch não foi executado.

    Abra duas conexões no SSMS e execute o código abaixo:

    BEGIN TRY

         

          BEGIN TRAN

               

                --ATUALIZA TODOS OS DADOS DO CAMPO NOME DA TABELA

                UPDATE CLIENTE SET NOME += '_'

               

    --AGUARDA 5 MINUTOS PARA DAR TEMPO DE REALIZAR O KILL

                WAITFOR DELAY '00:05:00'

               

                --ATUALIZA TODOS OS STATUS PARA 'L', VAI GERAR POR CAUSA DA CHECK CONSTRAINT

                UPDATE CLIENTE SET STATUS = 'L'

         

          COMMIT

         

    END TRY

    BEGIN CATCH

     

          --SE HOUVE ERRO, REVERTE A TRANSAÇÃO E LOGA O ERRO NA TABELA

          IF @@TRANCOUNT > 0

                ROLLBACK

     

          INSERT INTO TB_ERROR ( ELINE, EMESSAGE )

          SELECT

                ERROR_LINE(),

                ERROR_MESSAGE()        

               

    END CATCH

    Verifique o spid da conexão que está o script acima e na outra janela do SSMS execute o comando KILL passando o spid da conexão acima.

    Após matar o processo acima, volte na janela que encontra-se o script acima e veja que o SQL Server gerou o seguinte erro.

    Msg 0, Level 11, State 0, Line 0

    A severe error occurred on the current command.  The results, if any, should be discarded.

    Msg 0, Level 20, State 0, Line 0

    A severe error occurred on the current command.  The results, if any, should be discarded.

    Agora, verifique que a transação foi revertida mas que nenhuma linha foi inserida no log de erros:

    SELECT * FROM CLIENTE

    SELECT * FROM TB_ERROR

    Esse é um dos casos onde o catch não é executado, o mesmo acontece quando existe um timeout, devemos ficar atento quando estivermos utilizando o catch e fazendo algum tratamento dentro do mesmo.

    É isso ai, num próximo post irei mostrar outras situações onde o bloco catch não é executado.

    Abraços

    Comments (1)

    Please wait...
    Sorry, the comment you entered is too long. Please shorten it.
    You didn't enter anything. Please try again.
    Sorry, we can't add your comment right now. Please try again later.
    To add a comment, you need permission from your parent. Ask for permission
    Your parent has turned off comments.
    Sorry, we can't delete your comment right now. Please try again later.
    You've exceeded the maximum number of comments that can be left in one day. Please try again in 24 hours.
    Your account has had the ability to leave comments disabled because our systems indicate that you may be spamming other users. If you believe that your account has been disabled in error please contact Windows Live support.
    Complete the security check below to finish leaving your comment.
    The characters you type in the security check must match the characters in the picture or audio.

    To add a comment, sign in with your Windows Live ID (if you use Hotmail, Messenger, or Xbox LIVE, you have a Windows Live ID). Sign in


    Don't have a Windows Live ID? Sign up

    Show de bola meu amigo !!!..Tratamento de erros é uma prática indispensável em qq ambiente...e sua explicação foi perfeita !!!!
    Oct. 27

    Trackbacks

    The trackback URL for this entry is:
    http://demetriosqlserver.spaces.live.com/blog/cns!1D50CF1AC3A02CDE!270.trak
    Weblogs that reference this entry
    • None