368 Stimmen

SQL Server - Anhalten oder Unterbrechen der Ausführung eines SQL-Skripts

Gibt es eine Möglichkeit, die Ausführung eines SQL-Skripts in SQL Server sofort zu stoppen, z. B. mit einem "break"- oder "exit"-Befehl?

Ich habe ein Skript, das einige Überprüfungen und Nachforschungen durchführt, bevor es mit dem Einfügen beginnt, und ich möchte, dass es anhält, wenn eine der Überprüfungen oder Nachforschungen fehlschlägt.

418voto

Blorgbeard Punkte 96796

En raiserror Methode

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

Dadurch wird die Verbindung beendet und der Rest des Skripts wird nicht mehr ausgeführt.

Beachten Sie, dass sowohl der Schweregrad 20 oder höher als auch die WITH LOG sind notwendig, damit es auf diese Weise funktioniert.

Dies funktioniert sogar mit GO-Anweisungen, z. B.

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

Sie erhalten die Ausgabe:

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.

Beachten Sie, dass "ho" nicht gedruckt wird.

CAVEATS:

  • Dies funktioniert nur, wenn Sie als Administrator ("sysadmin"-Rolle) angemeldet sind, und führt auch dazu, dass Sie keine Datenbankverbindung haben.
  • Wenn Sie NICHT als Administrator angemeldet sind, schlägt der Aufruf von RAISEERROR() selbst fehl und das Skript wird weiter ausgeführt .
  • Beim Aufruf mit sqlcmd.exe wird der Exit-Code 2745 gemeldet.

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

Die noexec-Methode

Eine andere Methode, die mit GO-Anweisungen funktioniert, ist set noexec on ( docs ). Dies führt dazu, dass der Rest des Skripts übersprungen wird. Die Verbindung wird dadurch nicht abgebrochen, aber Sie müssen die noexec wieder aus, bevor Befehle ausgeführt werden können.

Beispiel:

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.

200voto

Gordon Bell Punkte 12689

Verwenden Sie einfach ein RETURN (es funktioniert sowohl innerhalb als auch außerhalb einer gespeicherten Prozedur).

60voto

Sglasses Punkte 601

Wenn Sie den SQLCMD-Modus verwenden können, dann wird die Beschwörungsformel

:on error exit

(EINSCHLIESSLICH des Doppelpunkts) bewirkt, dass RAISERROR das Skript tatsächlich anhält. Z.B.,

: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'

wird ausgegeben:

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

und der Stapel wird gestoppt. Wenn der SQLCMD-Modus nicht aktiviert ist, erhalten Sie einen Parse-Fehler bezüglich des Doppelpunkts. Leider ist das Skript nicht völlig kugelsicher, denn wenn das Skript ohne SQLCMD-Modus ausgeführt wird, kommt SQL Management Studio sogar an Parse-Fehlern vorbei! Wenn Sie die Skripte jedoch über die Befehlszeile ausführen, ist dies kein Problem.

21voto

Dave Swersky Punkte 34052

Ich würde RAISERROR nicht verwenden - SQL hat IF-Anweisungen, die für diesen Zweck verwendet werden können. Führen Sie die Validierung und die Abfragen durch und legen Sie lokale Variablen fest, und verwenden Sie dann den Wert der Variablen in IF-Anweisungen, um die Einfügungen an Bedingungen zu knüpfen.

Sie müssten nicht bei jedem Validierungstest das Ergebnis einer Variablen überprüfen. In der Regel reicht eine einzige Flag-Variable aus, um zu bestätigen, dass alle Bedingungen erfüllt sind:

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

Selbst wenn Ihre Validierung komplexer ist, sollten Sie nur einige wenige Flag-Variablen benötigen, die Sie in Ihre endgültige(n) Prüfung(en) einbeziehen.

17voto

Jordan Parker Punkte 1138

In SQL 2012+ können Sie Folgendes verwenden THROW .

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

Von MSDN:

Löst eine Ausnahme aus und übergibt die Ausführung an einen CATCH-Block eines TRY...CATCH-Konstrukts ... Wenn kein TRY...CATCH-Konstrukt vorhanden ist, wird die Sitzung beendet. Die Zeilennummer und die Prozedur, in der die Ausnahme ausgelöst wurde, werden gesetzt. Der Schweregrad wird auf 16 gesetzt.

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X