lista de erros de interrupção de lote no SQL server

9

No SQL Server, se XACT_ABORT estiver desativado, alguns erros encerrarão a instrução atual (por exemplo, fornecer o número incorreto de parâmetros para um procedimento armazenado que utiliza alguns parâmetros) e alguns erros abortarão o lote inteiro (por exemplo, fornecer parâmetros a um armazenamento armazenado procedimento que não aceita parâmetros). [Referência]: http://www.sommarskog.se/error-handling-I.html#scope-abortion .

O que eu gostaria de saber é se existe uma lista definitiva de quais erros são interrompidos em lotes e quais estão terminando a instrução.

Jamie Alford
fonte

Respostas:

6

Acredito que existem algumas exceções, mas a partir do MSDN (Mecanismo de Banco de Dados) :

As mensagens de erro com nível de gravidade 19 ou superior interrompem a execução do lote atual.

Erros que encerram a conexão com o banco de dados, geralmente com severidade de 20 a 25, não são tratados pelo bloco CATCH porque a execução é interrompida quando a conexão termina.

Portanto, parece que você pode obter uma lista definitiva da seguinte consulta (é claro que isso não permitirá que você filtre quais podem ser causadas pelo usuário T-SQL):

SELECT message_id, severity, [text]
FROM sys.messages
WHERE language_id = 1033 
AND severity >= 19
ORDER BY severity, message_id;

No SQL Server 2012, isso produz 210 linhas.

No SQL Server 2016, isso produz 256 linhas.

A propósito, não acredito que os dois cenários que você descreve em sua pergunta funcionem da maneira que você pensa, pelo menos não nas versões modernas do SQL Server. Tentei isso em 2012 e 2016 (acredito que o artigo de Erland descreve o comportamento do SQL Server 2000, que não me lembro se era diferente, mas não muito relevante hoje, mesmo que seja).

USE tempdb;
GO

CREATE PROCEDURE dbo.pA -- no parameters
AS PRINT 1
GO
CREATE PROCEDURE dbo.pB -- two parameters
@x INT, @y INT
AS PRINT 1
GO

SET XACT_ABORT OFF;
GO

EXEC dbo.pA @foo = 1; 
PRINT '### Calling procedure that doesn''t take parameters with a parameter';
GO

EXEC dbo.pB; 
PRINT '### Calling procedure that takes 2 parameters with no parameters';
GO

EXEC dbo.pB @x = 1; 
PRINT '### Calling procedure that takes 2 parameters with not enough parameters';
GO

EXEC dbo.pB @x = 1, @y = 2, @z = 3; 
PRINT '### Calling procedure that takes 2 parameters with too many parameters';
GO

Todos eles produzem erros de nível de gravidade 16 e todos prosseguem com o lote, conforme evidenciado pela saída de impressão:

Msg 8146, Nível 16, Estado 2, Procedimento pA, Linha 11 O
Procedimento pA não possui parâmetros e argumentos foram fornecidos.
### Procedimento de chamada que não aceita parâmetros com um parâmetro
Msg 201, Nível 16, Estado 4, Procedimento pB, Linha 14 O
procedimento ou função 'pB' espera o parâmetro '@x', que não foi fornecido.
### Procedimento de chamada que usa 2 parâmetros sem parâmetros
Msg 201, Nível 16, Estado 4, Procedimento pB, Linha 18 O
procedimento ou função 'pB' espera o parâmetro '@y', que não foi fornecido.
### Chamando o procedimento que usa 2 parâmetros com parâmetros insuficientes
Msg 8144, Nível 16, Estado 2, Procedimento pB, Linha 22
Procedimento ou função pB possui muitos argumentos especificados.
### Procedimento de chamada que usa 2 parâmetros com muitos parâmetros

Como eu suspeitava, existem exceções, é claro, como observado nos comentários. A falha de conversão é a gravidade 16, mas interrompe o lote:

SET XACT_ABORT OFF;
SELECT CONVERT (INT, 'foo');
PRINT 'Made it.'; -- no print happens

Os resultados não incluem a saída de impressão desta vez:

Msg 245, Nível 16, Estado 1
Falha na conversão ao converter o valor varchar 'foo' para o tipo de dados int.

Aaron Bertrand
fonte
Muito obrigado! Eu pensei que não seria capaz de usar o nível de gravidade como um indicador por causa da inconsistência anterior. Muito feliz em saber que não é o caso.
Jamie Alford
Aargh! Ainda existem alguns erros no nível de gravidade 16 que abortam o lote. Se eu selecionar e executar: begin tran print @@ TRANCOUNT print convert (int, 'abc') seguido por: print @@ TRANCOUNT Haverá um erro de nível 16, mas o lote será abortado.
Jamie Alford
BTW, se você descobrir casos em que a exceção é levantados com uma gravidade diferente da declarada, por favor informe-los através de conexão
Remus Rusanu
2

Além dos tipos de erros observados pelo @Aaron ( por exemplo, Gravidade> = 19 e falhas de conversão), os seguintes tipos de erros, observados na página do MSDN para TRY ... CATCH , também abortam um lote:

Os seguintes tipos de erros não são tratados por um bloco CATCH quando ocorrem no mesmo nível de execução que a construção TRY… CATCH:

  • Erros de compilação, como erros de sintaxe, que impedem a execução de um lote.

  • Erros que ocorrem durante a recompilação no nível da instrução, como erros de resolução de nome de objeto que ocorrem após a compilação devido à resolução de nome adiada.

Esses erros são retornados ao nível que executou o lote, o procedimento armazenado ou o acionador.

Nos exemplos abaixo, observe que três deles são do mesmo nível de gravidade 15.

EXEMPLO 1

SET XACT_ABORT OFF;
SELECT @NotDeclared; -- parse error
PRINT 'Do you see me?';

Devoluções:

Mensagem 137, Nível 15, Estado 2, Linha 2
Deve declarar a variável escalar "@NotDeclared".

EXEMPLO 2

SET XACT_ABORT OFF;
InvalidSQL; -- parse error
PRINT 'Do you see me?';

Devoluções:

Mensagem 102, Nível 15, Estado 1, Linha 2
Sintaxe incorreta perto de 'InvalidSQL'.

EXEMPLO 3

SET XACT_ABORT OFF;
SELECT 1 -- statement preceding THROW not terminated by semicolon
THROW 50505, N'Error, yo', 1; -- parse error
PRINT 'Do you see me?';

Devoluções:

Msg 102, Nível 15, Estado 1, Linha 3
Sintaxe incorreta próxima a '50505'.

EXEMPLO 4

SET XACT_ABORT OFF;
SELECT NoSuchColumn FROM sys.objects; -- compilation error
PRINT 'Do you see me?';

Devoluções:

Mensagem 207, nível 16, estado 1, linha 3
Nome da coluna inválido 'NoSuchColumn'.

Solomon Rutzky
fonte