lista błędów przerywania partii w serwerze SQL

9

W SQL Server, jeśli XACT_ABORT jest wyłączony, wówczas niektóre błędy zakończą bieżącą instrukcję (na przykład dostarczając niepoprawną liczbę parametrów do procedury składowanej, która przyjmuje niektóre parametry), a niektóre błędy przerywają całą partię (na przykład dostarczając parametry do przechowywanej procedura, która nie przyjmuje parametrów). [Odnośnik]: http://www.sommarskog.se/error-handling-I.html#scope-abortion .

Chciałbym wiedzieć, czy istnieje ostateczna lista błędów, które przerywają wsadowo, a które kończą instrukcję.

Jamie Alford
źródło

Odpowiedzi:

6

Uważam, że istnieje kilka wyjątków, ale z istotności błędów aparatu bazy danych (MSDN) :

Komunikaty o błędach o poziomie ważności 19 lub wyższym zatrzymują wykonywanie bieżącej partii.

Błędy, które kończą połączenie z bazą danych, zwykle o istotności od 20 do 25, nie są obsługiwane przez blok CATCH, ponieważ wykonywanie jest przerywane po zakończeniu połączenia.

Wygląda więc na to, że możesz uzyskać ostateczną listę z następującego zapytania (oczywiście nie pozwoli ci to odfiltrować, które mogą być spowodowane przez użytkownika T-SQL):

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

W SQL Server 2012 daje to 210 wierszy.

W SQL Server 2016 daje to 256 wierszy.

Nawiasem mówiąc, nie wierzę, że dwa scenariusze, które opisujesz w swoim pytaniu, działają tak, jak myślisz, przynajmniej nie we współczesnych wersjach SQL Server. Próbowałem tego zarówno w 2012, jak i 2016 r. (Wierzę, że artykuł Erlanda opisuje zachowanie SQL Server 2000, którego nie pamiętam, czy było inaczej, ale dziś niezbyt istotne, nawet jeśli tak).

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

Wszystkie z nich powodują błędy o poziomie istotności 16 i wszystkie z nich kontynuują partię, o czym świadczy wydruk:

Msg 8146, poziom 16, stan 2, procedura pA, wiersz 11
Procedura pA nie ma parametrów i podano argumenty.
###
Procedura wywoływania , która nie przyjmuje parametrów z parametrem Msg 201, poziom 16, stan 4, procedura pB, wiersz 14
Procedura lub funkcja „pB” oczekuje parametru „x”, który nie został podany.
###
Procedura wywoływania, która przyjmuje 2 parametry bez parametrów Msg 201, poziom 16, stan 4, procedura pB, linia 18
Procedura lub funkcja „pB” oczekuje parametru „yy”, który nie został podany.
###
Procedura wywoływania, która przyjmuje 2 parametry z niewystarczającą liczbą parametrów Msg 8144, poziom 16, stan 2, procedura pB, wiersz 22
Procedura lub funkcja pB ma za dużo podanych argumentów.
### Procedura wywoływania, która przyjmuje 2 parametry ze zbyt wieloma parametrami

Jak podejrzewałem, są oczywiście wyjątki, jak zauważono w komentarzach. Błąd konwersji to wskaźnik ważności 16, ale przerywa partię:

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

Tym razem wyniki nie uwzględniają wydruku:

Msg 245, poziom 16, stan 1
Konwersja nie powiodła się podczas konwersji wartości varchar „foo” na typ danych int.

Aaron Bertrand
źródło
Dziękuję Ci bardzo! Myślałem, że nie będę w stanie wykorzystać poziomu dotkliwości jako wskaźnika z powodu wcześniejszej niespójności. Bardzo się cieszę, że tak nie jest.
Jamie Alford,
Aargh! Nadal występują błędy 16 poziomu istotności, które przerywają partię. Jeśli wybiorę i wykonam: rozpocznij tran print @@ TRANCOUNT drukuj konwersję (int, 'abc'), a następnie: print @@ TRANCOUNT Wystąpi błąd poziomu 16, ale partia zostanie przerwana.
Jamie Alford,
BTW, jeśli odkryjesz przypadki, w których wyjątek jest zgłaszany z inną istotnością niż deklarowany, zgłoś je za pośrednictwem connect
Remus Rusanu
2

Oprócz rodzajów błędów odnotowanych przez @Aaron (tj. Ważność> = 19 i błędy konwersji), następujące typy błędów, odnotowane na stronie MSDN dla TRY ... CATCH , również przerwie partię:

Następujące typy błędów nie są obsługiwane przez blok CATCH, jeśli występują na tym samym poziomie wykonania co konstrukcja TRY… CATCH:

  • Błędy kompilacji, takie jak błędy składniowe, które uniemożliwiają uruchomienie partii.

  • Błędy występujące podczas ponownej kompilacji na poziomie instrukcji, takie jak błędy rozpoznawania nazw obiektów występujące po kompilacji z powodu odroczonego rozpoznawania nazw.

Te błędy są zwracane do poziomu, na którym uruchomiona została partia, procedura składowana lub wyzwalacz.

W poniższych przykładach zauważ, że trzy z nich mają nawet poziom ważności 15.

PRZYKŁAD 1

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

Zwroty:

Msg 137, poziom 15, stan 2, wiersz 2
Musi zadeklarować zmienną skalarną „@NieDeclared”.

PRZYKŁAD 2

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

Zwroty:

Msg 102, poziom 15, stan 1, wiersz 2
Niepoprawna składnia w pobliżu „InvalidSQL”.

PRZYKŁAD 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?';

Zwroty:

Msg 102, poziom 15, stan 1, wiersz 3
Niepoprawna składnia w pobliżu „50505”.

PRZYKŁAD 4

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

Zwroty:

Msg 207, poziom 16, stan 1, wiersz 3
Niepoprawna nazwa kolumny „NoSuchColumn”.

Solomon Rutzky
źródło