Como posso escrever código protegido que invoque o CATCH
bloco de código em todos os casos esperados * (sem fazer lixo estranho como envolver tudo em SQL dinâmico)?
Por exemplo, isso não funciona:
- Definir um trabalho do SQL Agent sem etapas
Tente iniciar o trabalho dentro de um
TRY/CATCH
BEGIN TRY EXEC msdb.dbo.sp_start_job @job_name = 'my_empty_job' END TRY BEGIN CATCH SELECT [MyError] = 'Error caught: ' + ISNULL(ERROR_MESSAGE(), 'NULL') END CATCH
Msg 22022, nível 16, estado 1, linha 0 SQLServerAgent Erro: solicitação para executar o trabalho my_empty_job (do usuário xyz) recusada porque o trabalho não tem etapas de trabalho.
Observe que a gravidade do erro é 16, portanto, não deve ter ignorado o bloco CATCH. pq?!?
Ele também ignora meu CATCH
bloqueio se o trabalho estiver ocupado lidando com uma solicitação (estou enviando spam para solicitações de parada e início em meus testes).
Msg 22022, nível 16, estado 1, linha 0 SQLServerAgent Erro: solicitação para executar o trabalho my_simple_job (do usuário xyz) recusada porque o trabalho já tem uma solicitação pendente do usuário xyz.
Caso relacionado: referência de servidor vinculado inválida
PS Por favor, não assuma que eu só quero uma solução de escopo restrito para lidar com a invocação de trabalho. Estou procurando uma solução genérica que possa reutilizar no futuro.
PPS Eu sou capaz de pegar o caso de tentar iniciar/parar um trabalho que não existe ("O @job_name especificado ('missing_job') não existe."). Por que isso se comporta de forma diferente?
* O que TRY/CATCH não lida (tl; dr gravidades de erro fora do intervalo (10, 20)
)
Não pode, infelizmente.
O MVP do SQL Server Erland Sommarskog tem uma série de artigos breves* sobre o assunto de tratamento de erros no SQL Server que começa aqui: Error and Transaction Handling in SQL Server
O problema que você está enfrentando com o trabalho do Agente é que ele chama um procedimento armazenado estendido, que é o que gera o erro. Em particular, esse erro vem do
master.dbo.xp_sqlagent_notify
.Erland aborda essa questão aqui :
Eu sei que você mencionou que não está interessado em soluções personalizadas que não são amplamente aplicáveis, mas acho que vale a pena mencionar que, ao lidar com procedimentos armazenados enviados pela Microsoft, uma solução para esse problema de TRY / CATCH é sempre capturar o código de retorno do procedimento. Se for diferente de zero, você pode gerar manualmente um erro para acionar o bloco CATCH (obrigado Dan Guzman ).
* breve, ha!