Guia do artigo:

TRY/CATCH

Os comandos TRY/CATCH são utilizados para controlar erros em grupos de comandos do SQL Server. Confira abaixo a sintaxe do uso do TRY/CATCH.


BEGIN TRY

{ comando_sql | bloco_comando }

END TRY

BEGIN CATCH

{ comando_sql | bloco_comando }

END CATCH

[ ; ]

Acima temos o comando_sql, que representa qualquer comando Transact-SQL, assim como o bloco_comando refere-se a qualquer bloco de comando que esteja em um bloco BEGIN/END ou em um batch.

Seguindo o uso nas linguagens de programação orientadas a objeto, o bloco TRY é utilizado para inserirmos os comandos e, se houver algum erro, outro grupo de comandos, existente no bloco CATCH irá assumir o controle.

Caso os comandos dentro do bloco TRY não apresentarem erros, o controle será passado ao comando localizado logo após o comando END CATCH, após a execução do último comando do bloco TRY.

O uso dos blocos TRY/CATCH contém algumas considerações importantes, abaixo apresento algumas delas:

  • Qualquer erro de execução com o valor de severidade superior a 10 e que não finaliza a conexão com o banco de dados é capturado por TRY/CATCH.
  • Qualquer comando que for inserido entre os comandos END TRY e BEGIN CATCH ocasionará um erro de sintaxe. Por isso é imprescindível que o bloco TRY seja imediatamente seguido por um bloco CATCH associado;
  • Por meio de alguns comandos, como RAISERROR, PRINT e até conjuntos de SELECT, podemos retornar o erro de dentro do bloco CATCH para nossa aplicação;
  • Blocos TRY e CATCH podem conter comandos TRY e CATCH aninhados;
  • O SQL Server possui comandos chamados GOTO, que podem ser usados para ir para um local específico, localizada no mesmo TRY ou CATCH. Os comandos GOTO também servem para sair de um bloco TRY ou CATCH.

Com o objetivo de obter informações a respeito do erro que provocar a execução do bloco CATCH, temos várias funções do sistema que devem ser usadas no bloco CATCH. A tabela abaixo descreve as funções do sistema para esse fim:

Função do Sistema Descrição
ERROR_NUMBER() Retorna o número do erro.
ERROR_SEVERITY() Retorna a severidade do erro.
ERROR_STATE() Retorna o número do estado de erro.
ERROR_PROCEDURE() Retorna o nome da Trigger ou da Stored Procedure onde aconteceu o erro.
ERROR_LINE() Retorna o número da linha dentro da rotina que causou o erro.
ERROR_MESSAGE() Retorna o texto completo da mensagem de erro, incluindo os parâmetros como nomes de objetos.

Na Listagem 01 temos um exemplo de uso dos blocos TRY/CATCH.

Listagem 01. Exemplo com o uso dos blocos TRY/CATCH.

BEGIN TRY
  PRINT 'Execução Iniciada'
  SELECT * FROM Products
END TRY
BEGIN CATCH
  SELECT
    ERROR_MESSAGE() AS MensagemdeErro,
    ERROR_NUMBER() AS NúmeroErrado
END CATCH

EXECUTE

O comando EXECUTE (ou EXEC) quase sempre é usado para rodar Stored Procedures. Abaixo vemos a sintaxes do uso do EXECUTE.


EXECUTE [@Retorno =] { Nome_da_Procedure }

Nessa sintaxe, a mais usada, temos @Retorno e Nome_da_Procedure. @Retorno representa uma variável que armazena o estado de uma Stored Procedure e deve ser declarada antes de ser usada com o EXECUTE. @Retorno é uma variável opcional. Como é de se esperar Nome_da_Procedure representa o nome da Stored Procedure a ser executada.

Stored Procedure

Segundo a definição mais conhecida, uma Stored Procedure é uma coleção de comandos SQL criada para utilização, permanente ou temporária, em uma sessão de usuário ou por todos os usuários.

Podemos executar as Stored Procedures no momento em que o SQL Server é iniciado, em períodos específicos do dia ou até mesmo em um horário específico.

As Stored Procedures podem ser de tipos diferentes. Elas podem ser System Stored Procedures, Stored Procedures Locais, Remotas, Temporárias Locais e Globais e Extended Stored Procedure.

Vamos se focar nas Stored Procedures Locais, que são as criadas em bancos de dados individuais de usuários.

Abaixo, na Listagem 02, é visto um exemplo prático da criação de uma proc (nome abreviado para Stored Procedure) de SELECT, sem parâmetros.

Listagem 02. Exemplo com Stored Procedure sem parâmetros

CREATE PROCEDURE SP_SELECT_USUARIO
AS
  BEGIN
    SELECT IdUsuario, Usuario, Idade
      FROM Usuario
  END
  

Lembrando que o comando CREATE só é utilizado na primeira vez em que a Procedure é criada. Nas demais vezes é usado o comando ALTER;.

Para executarmos essa Procedure é só usarmos o comando EXECUTE ou EXEC, como a Listagem 03 nos mostra abaixo.

Listagem 03. Execução da Stored Procedure sem parâmetros.

  EXEC SP_SELECT_USUARIO
  

Parâmetros

As Procedures aceitam tanto parâmetros de entrada como retornam parâmetros de saída. As Procedures não retornam valores no lugar de seus nomes. Além disso, não podem ser usadas no lugar de expressões. Isso é o que difere a Procedure de Functions (Funções).

A Listagem 04 nos mostra um exemplo de uma Procedure de INSERT com parâmetros de entrada e um parâmetro de saída, que retornará o ID gerado após o INSERT, para o respectivo parâmetro.

Listagem 04. Execução da Stored Procedure com parâmetros de entrada e saída.

CREATE PROCEDURE SP_INSERT_USUARIO
        @IdUsuario      AS INT OUTPUT
      , @Usuario        AS VARCHAR(50)
      , @Idade          AS SMALLINT
      , @DataCadastro   AS DATETIME
AS
  BEGIN
    INSERT INTO
        Usuario
    VALUES
        (@Usuario,@Idade,@DataCadastro)
    SELECT
        @IdUsuario = SCOPE_IDENTITY()
  END
  

Notem que o parâmetro @IdUsuario contém ao final de sua declaração a palavra OUTPUT. Esse tipo de parâmetro também pode ser chamado de parâmetro por referência. Assim, ao final do INSERT, é gerado o ID do registro inserido e, por meio do SCOPE_IDENTITY(), é retornado este ID para o meu parâmetro.

Quando usamos o OUTPUT, podemos manter qualquer valor atribuído ao parâmetro enquanto a procedure é executada, mesmo depois que ela tenha sido finalizada.

RETURN

Através do comando RETURN, é possível fazer com que a procedure retorne um valor, que deve ser um número inteiro. A Listagem 05 ilustra um exemplo com o uso do RETURN.

Listagem 05. Exemplo de Procedure com o uso do RETURN.

ALTER PROCEDURE SP_INSERT_USUARIO
        @IdUsuario      AS INT OUTPUT
      , @Usuario        AS VARCHAR(50)
      , @Idade          AS SMALLINT
      , @DataCadastro   AS DATETIME
AS
  BEGIN
    INSERT INTO
        Usuario
    VALUES
        (@Usuario,@Idade,@DataCadastro)
    IF @@ERROR <> 0
      BEGIN
        RAISERROR(50002,16,1)
          RETURN -1
      END
    ELSE
      SELECT
          @IdUsuario = SCOPE_IDENTITY()
  END

Assim, se houver erros no momento que o INSERT é executado no banco, a procedure nos retornará -1, assim podemos saber se o registro foi gravado no banco ou não.

DROP

Para excluir uma Procedure utilizamos o comando DROP, como pode ser visto abaixo, na Listagem 06.

Listagem 06. Exclusão de uma Stored Procedure.

DROP PROCEDURE SP_INSERT_USUARIO

Deixo como dica para que vocês procurem mais informações a respeito das Stored Procedures, que são uma “mão na roda” para desenvolver aplicações customizadas, com segurança e sem deixar aquele monte de instruções SQL direto na aplicação, gerando assim menos erros para você e mais confiabilidade para o seu cliente!