SQL Server-zatrzymanie lub przerwanie wykonywania skryptu SQL

Czy istnieje sposób, aby natychmiast zatrzymać wykonywanie skryptu SQL w SQL server, jak polecenie" break "lub" exit"?

Mam skrypt, który wykonuje walidację i wyszukiwanie przed rozpoczęciem wstawiania i chcę, aby przestał, jeśli którekolwiek z walidacji lub wyszukiwania nie powiedzie się.

Author: Blorgbeard, 2009-03-18

18 answers

Metoda raiserror

raiserror('Oh no a fatal error', 20, -1) with log

Spowoduje to przerwanie połączenia, tym samym zatrzymując resztę skryptu przed uruchomieniem.

Zauważ, że zarówno poziom dotkliwości 20 lub wyższy, jak i opcja WITH LOG są niezbędne, aby działać w ten sposób.

To działa nawet z deklaracjami GO, np.

print 'hi'
go
raiserror('Oh no a fatal error', 20, -1) with log
go
print 'ho'

Da ci wyjście:

hi
Msg 2745, Level 16, State 2, Line 1
Process ID 51 has raised user error 50000, severity 20. SQL Server is terminating this process.
Msg 50000, Level 20, State 1, Line 1
Oh no a fatal error
Msg 0, Level 20, State 0, Line 0
A severe error occurred on the current command.  The results, if any, should be discarded.

Zauważ, że 'ho' nie jest drukowany.

Zastrzeżenia:

  • to działa tylko wtedy, gdy jesteś zalogowany jako admin (rola' sysadmin'), a także pozostawia cię bez połączenia z bazą danych.
  • jeśli nie jesteś zalogowany jako admin, wywołanie RAISEERROR() nie powiedzie się , a skrypt będzie kontynuował wykonywanie.
  • podczas wywoływania z sqlcmd.exe, kod wyjścia 2745 zostanie zgłoszony.

Odniesienie: http://www.mydatabasesupport.com/forums/ms-sqlserver/174037-sql-server-2000-abort-whole-script.html#post761334

Noexec metoda

Inną metodą, która działa z poleceniami GO jest set noexec on. Powoduje to pominięcie reszty skryptu. Nie przerywa połączenia, ale musisz ponownie wyłączyć noexec, zanim jakiekolwiek polecenia zostaną wykonane.

Przykład:

print 'hi'
go

print 'Fatal error, script will not continue!'
set noexec on

print 'ho'
go

-- last line of the script
set noexec off -- Turn execution back on; only needed in SSMS, so as to be able 
               -- to run this script again in the same session.
 312
Author: Blorgbeard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-18 16:43:00

Wystarczy użyć RETURN (będzie działać zarówno wewnątrz, jak i na zewnątrz procedury składowanej).

 153
Author: Gordon Bell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-18 17:23:19

Jeśli możesz użyć trybu SQLCMD, to inkantacja

:on error exit

(łącznie z dwukropkiem) spowoduje, że RAISERROR faktycznie zatrzyma skrypt. Np.,

:on error exit

IF NOT EXISTS (SELECT * FROM sys.objects WHERE object_id = OBJECT_ID(N'[dbo].[SOMETABLE]') AND type in (N'U')) 
    RaisError ('This is not a Valid Instance Database', 15, 10)
GO

print 'Keep Working'

Wyświetli:

Msg 50000, Level 15, State 10, Line 3
This is not a Valid Instance Database
** An error was encountered during execution of batch. Exiting.

I Partia zatrzyma się. Jeśli tryb SQLCMD nie jest włączony, pojawi się błąd analizy dwukropka. Unfultuantely, to nie jest całkowicie kuloodporne, jak gdyby skrypt jest uruchamiany bez bycia w trybie SQLCMD, SQL Managment Studio breezes prawo przeszłości nawet parse błędy czasu! / Align = "left" / im z linii poleceń, to jest w porządku.

 41
Author: Sglasses,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-04-07 06:13:39

Nie użyłbym RAISERROR-SQL ma poleceń IF, które mogą być użyte do tego celu. Wykonaj walidację i wyszukiwanie oraz ustaw zmienne lokalne, a następnie użyj wartości zmiennych w instrukcjach IF, aby wstawianie było warunkowe.

Nie trzeba sprawdzać zmiennego wyniku każdego testu walidacyjnego. Zazwyczaj można to zrobić tylko z jedną zmienną flag, aby potwierdzić, że wszystkie warunki przeszły:

declare @valid bit

set @valid = 1

if -- Condition(s)
begin
  print 'Condition(s) failed.'
  set @valid = 0
end

-- Additional validation with similar structure

-- Final check that validation passed
if @valid = 1
begin
  print 'Validation succeeded.'

  -- Do work
end

Nawet jeśli Walidacja jest bardziej złożona, powinieneś potrzebować tylko kilku znaczników zmienne, które należy uwzględnić w końcowych kontrolach.

 20
Author: Dave Swersky,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-05-17 11:24:33

Możesz zawinąć instrukcję SQL w pętlę WHILE I użyć BREAK w razie potrzeby

WHILE 1 = 1
BEGIN
   -- Do work here
   -- If you need to stop execution then use a BREAK


    BREAK; --Make sure to have this break at the end to prevent infinite loop
END
 12
Author: Jon Erickson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-18 17:27:14

Rozszerzyłem rozwiązanie noexec on / off pomyślnie z transakcją, aby uruchomić skrypt w sposób wszystko lub nic.

set noexec off

begin transaction
go

<First batch, do something here>
go
if @@error != 0 set noexec on;

<Second batch, do something here>
go
if @@error != 0 set noexec on;

<... etc>

declare @finished bit;
set @finished = 1;

SET noexec off;

IF @finished = 1
BEGIN
    PRINT 'Committing changes'
    COMMIT TRANSACTION
END
ELSE
BEGIN
    PRINT 'Errors occured. Rolling back changes'
    ROLLBACK TRANSACTION
END

Najwyraźniej kompilator " rozumie "zmienną @ finished W IF, nawet jeśli wystąpił błąd i wykonanie zostało wyłączone. Wartość jest jednak ustawiona na 1 tylko wtedy, gdy wykonanie nie zostało wyłączone. Dlatego mogę odpowiednio zatwierdzić lub wycofać transakcję.

 11
Author: Tz_,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-10-25 12:27:31

W SQL 2012+ możesz użyć THROW.

THROW 51000, 'Stopping execution because validation failed.', 0;
PRINT 'Still Executing'; -- This doesn't execute with THROW

Z MSDN:

Podnosi wyjątek i przenosi wykonanie do bloku CATCH z konstrukcji try ... CATCH ... Jeśli konstrukcja try ... CATCH nie jest dostępna, sesja zostaje zakończona. Ustawia się numer linii i procedurę, w której podnoszony jest wyjątek. Stopień ciężkości jest ustawiony na 16.

 11
Author: Jordan Parker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-11-19 16:21:15

Czy to procedura składowana? Jeśli tak, myślę, że możesz po prostu zrobić Return, np. "Return NULL";

 7
Author: mtazva,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-18 17:07:52

Dalsze udoskonalanie metody Sglasses, powyższe linie wymuszają użycie trybu SQLCMD, i albo treminuje scirpt, jeśli nie używa trybu sqlcmd lub używa :on error exit, aby zakończyć przy jakimkolwiek błędzie
CONTEXT_INFO jest używany do śledzenia stanu.

SET CONTEXT_INFO  0x1 --Just to make sure everything's ok
GO 
--treminate the script on any error. (Requires SQLCMD mode)
:on error exit 
--If not in SQLCMD mode the above line will generate an error, so the next line won't hit
SET CONTEXT_INFO 0x2
GO
--make sure to use SQLCMD mode ( :on error needs that)
IF CONTEXT_INFO()<>0x2 
BEGIN
    SELECT CONTEXT_INFO()
    SELECT 'This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!'
    RAISERROR('This script must be run in SQLCMD mode! (To enable it go to (Management Studio) Query->SQLCMD mode)\nPlease abort the script!',16,1) WITH NOWAIT 
    WAITFOR DELAY '02:00'; --wait for the user to read the message, and terminate the script manually
END
GO

----------------------------------------------------------------------------------
----THE ACTUAL SCRIPT BEGINS HERE-------------
 7
Author: jaraics,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-08-24 15:55:50

Proponuję zawinąć odpowiedni blok kodu w blok try catch. Następnie możesz użyć zdarzenia Raiserror o wadze 11, aby przebić się do bloku catch, jeśli chcesz. Jeśli chcesz tylko zwiększyć liczbę błędów, ale kontynuować wykonywanie w ramach bloku try, użyj niższej wagi.

Ma sens?

Cheers, John

[Edited to include BOL Reference]

Http://msdn.microsoft.com/en-us/library/ms175976(SQL. 90). aspx

 6
Author: John Sansom,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-19 12:29:49

Możesz użyć RAISERROR .

 5
Author: Mladen Prajdic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-18 17:05:27

Możesz zmienić przebieg wykonania używając GOTO poleceń:

IF @ValidationResult = 0
BEGIN
    PRINT 'Validation fault.'
    GOTO EndScript
END

/* our code */

EndScript:
 5
Author: Charlie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-09 15:21:25

Żaden z nich nie działa z wyrażeniami "GO". W tym kodzie, niezależnie od tego, czy dotkliwość wynosi 10 czy 11, otrzymasz ostateczną instrukcję PRINT.

Skrypt Testowy:

-- =================================
PRINT 'Start Test 1 - RAISERROR'

IF 1 = 1 BEGIN
    RAISERROR('Error 1, level 11', 11, 1)
    RETURN
END

IF 1 = 1 BEGIN
    RAISERROR('Error 2, level 11', 11, 1)
    RETURN
END
GO

PRINT 'Test 1 - After GO'
GO

-- =================================
PRINT 'Start Test 2 - Try/Catch'

BEGIN TRY
    SELECT (1 / 0) AS CauseError
END TRY
BEGIN CATCH
    SELECT ERROR_MESSAGE() AS ErrorMessage
    RAISERROR('Error in TRY, level 11', 11, 1)
    RETURN
END CATCH
GO

PRINT 'Test 2 - After GO'
GO

Wyniki:

Start Test 1 - RAISERROR
Msg 50000, Level 11, State 1, Line 5
Error 1, level 11
Test 1 - After GO
Start Test 2 - Try/Catch
 CauseError
-----------

ErrorMessage
--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Divide by zero error encountered.

Msg 50000, Level 11, State 1, Line 10
Error in TRY, level 11
Test 2 - After GO

Jedynym sposobem, aby to zadziałało, jest napisanie skryptu bez GO instrukcji. Czasami to proste. Czasami jest to dość trudne. (Użyj czegoś w rodzaju IF @error <> 0 BEGIN ....)

 4
Author: Rob Garrison,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-10-27 12:59:20

To było moje rozwiązanie:

...

BEGIN
    raiserror('Invalid database', 15, 10)
    rollback transaction
    return
END
 3
Author: Casper Leon Nielsen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-06-27 08:40:44

Możesz użyć polecenia GOTO. Spróbuj tego. To jest pełne wykorzystanie dla Ciebie.

WHILE(@N <= @Count)
BEGIN
    GOTO FinalStateMent;
END

FinalStatement:
     Select @CoumnName from TableName
 2
Author: Vishal Kiri,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-07 06:58:18

Thx za odpowiedź!

raiserror() działa dobrze, ale nie należy zapominać return oświadczenie inaczej skrypt kontynuuje bez błędu! (hense raiserror nie jest "throwerror"; -)) i oczywiście robi rollback jeśli to konieczne!

raiserror() miło jest powiedzieć osobie, która wykonuje scenariusz, że coś poszło nie tak.

 1
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-03-31 13:52:18

Jeśli po prostu wykonujesz skrypt w Management Studio i chcesz zatrzymać wykonanie lub transakcję rollback (jeśli jest używana) przy pierwszym błędzie, najlepszym moim zdaniem sposobem jest użycie try catch block (SQL 2005). Działa to dobrze w Management studio, jeśli wykonujesz plik skryptu. Przechowywany proc również może z niego korzystać.

 1
Author: Bhargav Shah,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-07-05 07:34:31

Używam RETURN tutaj cały czas, działa w skrypcie lub Stored Procedure

Upewnij się, że ROLLBACK transakcja, jeśli jesteś w jednym, w przeciwnym razie RETURN natychmiast spowoduje otwarcie niezakontraktowanej transakcji

 1
Author: jerryhung,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-28 19:02:36