список ошибок пакетного прерывания на сервере SQL

9

В SQL Server, если XACT_ABORT выключен, некоторые ошибки прерывают текущую инструкцию (например, предоставление неверного числа параметров хранимой процедуре, которая принимает некоторые параметры), а некоторые ошибки отменяют весь пакет (например, передача параметров в хранимую процедуру). процедура, которая не принимает параметры). [Ссылка]: http://www.sommarskog.se/error-handling-I.html#scope-abortion .

То, что я хотел бы знать, есть ли определенный список, какие ошибки прерывают пакет, а какие - оператор завершения.

Джейми Алфорд
источник

Ответы:

6

Я полагаю, что есть несколько исключений, но из серьезности ошибок компонента Database Engine (MSDN) :

Сообщения об ошибках с уровнем серьезности 19 или выше останавливают выполнение текущего пакета.

Ошибки, которые завершают соединение с базой данных, обычно с серьезностью от 20 до 25, не обрабатываются блоком CATCH, потому что выполнение прекращается, когда соединение завершается.

Таким образом, кажется, что вы могли бы получить окончательный список из следующего запроса (конечно, это не позволит вам отфильтровать, какие из них могут быть вызваны пользователем T-SQL):

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

В SQL Server 2012 это создает 210 строк.

В SQL Server 2016 это производит 256 строк.

Кстати, я не верю, что два сценария, которые вы описываете в своем вопросе, работают так, как вы думаете, по крайней мере, в современных версиях SQL Server. Я пробовал это как в 2012, так и в 2016 году (я полагаю, что статья Эрланда описывает поведение SQL Server 2000, которое я не помню, было ли оно каким-то другим, но не очень актуальным сегодня, даже если и так).

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

Все это приводит к ошибкам уровня серьезности 16, и все они продолжают работу с пакетом, что подтверждается выводом на печать:

Сообщение 8146, Уровень 16, Состояние 2, Процедура pA, Строка 11
Процедура pA не имеет параметров и аргументы были предоставлены.
### Вызов процедуры, которая не принимает параметры с параметром
Msg 201, Уровень 16, Состояние 4, Процедура pB, Строка 14
Процедура или функция 'pB' ожидает параметр '@x', который не был предоставлен.
### Вызов процедуры, которая принимает 2 параметра без параметров
Msg 201, Уровень 16, Состояние 4, Процедура pB, Строка 18
Процедура или функция 'pB' ожидает параметр '@y', который не был предоставлен.
### Вызов процедуры, которая принимает 2 параметра с недостаточным количеством параметров
Msg 8144, Уровень 16, Состояние 2, Процедура pB, Строка 22 В
процедуре или функции pB указано слишком много аргументов.
### Вызов процедуры, которая принимает 2 параметра со слишком многими параметрами

Как я и подозревал, есть, конечно, исключения, как отмечено в комментариях. Ошибка преобразования - серьезность 16, но прерывает пакет:

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

На этот раз результаты не включают вывод на печать:

Сообщение 245, уровень 16, состояние 1 Не
удалось выполнить преобразование при преобразовании значения varchar 'foo' в тип данных int.

Аарон Бертран
источник
Большое спасибо! Я думал, что не смогу использовать уровень серьезности в качестве индикатора из-за предыдущей несогласованности. Очень рад слышать, что это не так.
Джейми Олфорд
Aargh! Есть все еще некоторые ошибки уровня серьезности 16, которые прервут пакет. Если я выберу и выполню: begin tran print @@ TRANCOUNT print convert (int, 'abc'), а затем: print @@ TRANCOUNT Ошибка 16 уровня, но пакет будет прерван.
Джейми Олфорд
Кстати, если вы обнаружите случаи, когда исключение возникает с серьезностью, отличной от заявленной, сообщите об этом через connect
Remus Rusanu
2

В дополнение к типам ошибок, отмеченных @Aaron (т. Е. Серьезность> = 19 и сбои преобразования), следующие типы ошибок, отмеченные на странице MSDN для TRY ... CATCH , также прервет пакет:

Следующие типы ошибок не обрабатываются блоком CATCH, когда они происходят на том же уровне выполнения, что и конструкция TRY… CATCH:

  • Ошибки компиляции, такие как синтаксические ошибки, которые мешают запуску пакета.

  • Ошибки, возникающие при перекомпиляции на уровне операторов, такие как ошибки разрешения имен объектов, возникающие после компиляции из-за отложенного разрешения имен.

Эти ошибки возвращаются на уровень, на котором выполнялся пакет, хранимая процедура или триггер.

В приведенных ниже примерах обратите внимание, что три из них даже имеют уровень серьезности 15.

Пример 1

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

Возвращает:

Сообщение 137, Уровень 15, Состояние 2, Строка 2
Необходимо объявить скалярную переменную "@NotDeclared".

Пример 2

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

Возвращает:

Сообщение 102, уровень 15, состояние 1, строка 2
Неверный синтаксис рядом с InvalidSQL.

Пример 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?';

Возвращает:

Сообщение 102, Уровень 15, Состояние 1, Строка 3
Неверный синтаксис рядом с '50505'.

Пример 4

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

Возвращает:

Сообщение 207, уровень 16, состояние 1, строка 3
Неверное имя столбца «NoSuchColumn».

Соломон Руцкий
источник