Z dokumentacji RAISERROR ( wyróżnienie moje):
Poziomy ważności od 0 do 18 mogą być określone przez dowolnego użytkownika. Poziomy ważności od 19 do 25 mogą być określone tylko przez członków sysadmin stałej roli serwera lub użytkowników z uprawnieniami ALTER TRACE. Dla poziomów ważności od 19 do 25 wymagana jest opcja Z LOGEM.
Jest wysoce prawdopodobne, że zleceniodawca wykonuje skrypt, ponieważ nie spełnia tych kryteriów.
Nie ma nic złego w korzystaniu RAISERROR
; po prostu używasz nadmiernego poziomu istotności. Używam poziomu 16 jako domyślnego dla zgłaszanego błędu i sekwencja zostanie zakończona. Jeśli chcesz być bardziej dokładny, możesz śledzić poziomy podane przez sam Microsoft:
Powiedziawszy to wszystko, w zależności od kontekstu skryptu, użycie RAISERROR
może nie wystarczyć, ponieważ samo nie „wychodzi” ze skryptu (przy użyciu normalnych poziomów ważności).
Na przykład:
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Executed! */
Będzie to zarówno podnieść błąd i zwraca zestaw wyników.
Aby natychmiast zakończyć skrypt, wolę go używać RETURN
(używanie GOTO
konstrukcji typu -type jest ogólnie odradzane w większości kręgów programistycznych, w których istnieją alternatywy):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
Lub obsłużyć błąd przy użyciu TRY/CATCH
, co spowoduje przeskakiwanie wykonania do CATCH
bloku, jeśli wskaźnik ważności wynosi 11 lub więcej:
BEGIN TRY
RAISERROR(N'Test', 16, 1);
SELECT 1; /* Not executed */
END TRY
BEGIN CATCH
SELECT 2; /* Executed */
END CATCH
BEGIN TRY
RAISERROR(N'Test', 10, 1);
SELECT 1; /* Executed */
END TRY
BEGIN CATCH
SELECT 2; /* Not executed */
END CATCH
Osobny problem polega na tym, że skrypt obejmuje wiele partii - zamknie RETURN
tylko partię :
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
SELECT 2; /* Executed! */
Aby to naprawić, możesz sprawdzić @@ERROR
na początku każdej partii:
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
RETURN;
SELECT 2; /* Not executed */
Edycja: Jak słusznie zauważył Martin Smith w komentarzach, działa to tylko dla 2 partii. Aby rozszerzyć do 3 lub więcej partii, możesz kaskadowo zgłaszać błędy w ten sposób (uwaga: GOTO
metoda nie rozwiązuje tego problemu, ponieważ etykieta docelowa musi być zdefiniowana w partii):
RAISERROR(N'Test', 16, 1);
RETURN;
SELECT 1; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 2; /* Not executed */
GO
IF (@@ERROR != 0)
BEGIN
RAISERROR(N'Error already raised. See previous errors.', 16, 1);
RETURN;
END
SELECT 3; /* Not executed */
Lub, jak wskazuje również, możesz użyć tej SQLCMD
metody, jeśli jest to odpowiednie dla twojego środowiska.