lista de errores de aborto por lotes en el servidor SQL

9

En SQL Server, si XACT_ABORT está desactivado, algunos errores terminarán la declaración actual (por ejemplo, proporcionar el número incorrecto de parámetros a un procedimiento almacenado que toma algunos parámetros) y algunos errores anularán todo el lote (por ejemplo, proporcionar parámetros a un procedimiento que no toma parámetros). [Referencia]: http://www.sommarskog.se/error-handling-I.html#scope-abortion .

Lo que me gustaría saber es si hay una lista definitiva de qué errores se anulan por lotes y cuáles terminan las declaraciones.

Jamie Alford
fuente

Respuestas:

6

Creo que hay algunas excepciones, pero de las Severidades de error del motor de base de datos (MSDN) :

Los mensajes de error con un nivel de gravedad de 19 o superior detienen la ejecución del lote actual.

El bloque CATCH no maneja los errores que finalizan la conexión de la base de datos, generalmente con una gravedad de 20 a 25, porque la ejecución se cancela cuando finaliza la conexión.

Por lo tanto, parece que podría obtener una lista definitiva de la siguiente consulta (por supuesto, esto no le permitirá filtrar cuáles pueden ser causadas por el usuario T-SQL):

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

En SQL Server 2012, esto produce 210 filas.

En SQL Server 2016, esto produce 256 filas.

Por cierto, no creo que los dos escenarios que describas en tu pregunta funcionen como piensas, al menos no en las versiones modernas de SQL Server. Probé esto tanto en 2012 como en 2016 (creo que el artículo de Erland describe el comportamiento de SQL Server 2000, que no recuerdo si fuera diferente, pero no muy relevante hoy, incluso si es así).

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 estos producen errores de nivel de gravedad 16, y todos proceden con el lote, como lo demuestra la salida de impresión:

El mensaje 8146, Nivel 16, Estado 2, Procedimiento pA, Línea 11,
Procedimiento pA no tiene parámetros y se proporcionaron argumentos.
### El procedimiento de llamada que no toma parámetros con un parámetro
Msg 201, Nivel 16, Estado 4, Procedimiento pB, Línea 14
Procedimiento o la función 'pB' espera el parámetro '@x', que no se suministró.
### Procedimiento de llamada que toma 2 parámetros sin parámetros
Msg 201, Nivel 16, Estado 4, Procedimiento pB, Línea 18 El
procedimiento o la función 'pB' espera el parámetro '@y', que no se suministró.
### El procedimiento de llamada que toma 2 parámetros con parámetros insuficientes
Msg 8144, Nivel 16, Estado 2, Procedimiento pB, Línea 22
Procedimiento o función pB tiene demasiados argumentos especificados.
### Procedimiento de llamada que toma 2 parámetros con demasiados parámetros

Como sospechaba, hay excepciones, por supuesto, como se señala en los comentarios. El error de conversión es de gravedad 16 pero aborta el lote:

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

Los resultados no incluyen la salida de impresión esta vez:

Msg 245, Nivel 16, Estado 1 La
conversión falló al convertir el valor varchar 'foo' al tipo de datos int.

Aaron Bertrand
fuente
¡Muchas gracias! Pensé que no podría usar el nivel de gravedad como un indicador debido a la inconsistencia previa. Me alegra saber que ese no es el caso.
Jamie Alford el
Aargh! Todavía hay algunos errores de nivel de gravedad 16 que anularán el lote. Si selecciono y ejecuto: comenzar tran print @@ TRANCOUNT print convert (int, 'abc') seguido de: print @@ TRANCOUNT Habrá un error de nivel 16 pero el lote será abortado.
Jamie Alford
Por cierto, si descubre casos en los que la excepción se produce con una gravedad diferente de la declarada, informe de ellos a través de connect
Remus Rusanu
2

Además de los tipos de errores observados por @Aaron (es decir, gravedad> = 19 y fallas de conversión), los siguientes tipos de errores, anotados en la página de MSDN para TRY ... CATCH , también abortarán un lote:

Los siguientes tipos de errores no son manejados por un bloque CATCH cuando ocurren en el mismo nivel de ejecución que la construcción TRY ... CATCH:

  • Errores de compilación, como los errores de sintaxis, que impiden que se ejecute un lote.

  • Errores que ocurren durante la recompilación a nivel de declaración, como los errores de resolución de nombre de objeto que ocurren después de la compilación debido a la resolución de nombre diferido.

Estos errores se devuelven al nivel que ejecutó el lote, el procedimiento almacenado o el desencadenante.

En los ejemplos a continuación, tenga en cuenta que tres de ellos son incluso Nivel de gravedad 15.

EJEMPLO 1

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

Devoluciones:

Mensaje 137, Nivel 15, Estado 2, Línea 2
Debe declarar la variable escalar "@NotDeclared".

EJEMPLO 2

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

Devoluciones:

Mensaje 102, Nivel 15, Estado 1, Línea 2
Sintaxis incorrecta cerca de 'InvalidSQL'.

EJEMPLO 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?';

Devoluciones:

Mensaje 102, Nivel 15, Estado 1, Línea 3
Sintaxis incorrecta cerca de '50505'.

EJEMPLO 4

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

Devoluciones:

Mensaje 207, Nivel 16, Estado 1, Línea 3
Nombre de columna no válido 'NoSuchColumn'.

Solomon Rutzky
fuente