it-swarm.com.de

So unterbrechen Sie die Ausführung von SQL-Skripten

Ich arbeite an einem SQL-Skript und muss das Skript nicht mehr fortsetzen, wenn einige Bedingungen nicht erfüllt sind.

Als ich es googelte, stellte ich fest, dass der RaisError mit dem Schweregrad 20 ihn beendet. Aus bestimmten Gründen kann ich diese Option jedoch nicht verwenden.

Kann mir bitte mitteilen, welche Alternativen möglich sind, um die Ausführung von SQL-Skripten zu stoppen.

16
New Developer

Aus der RAISERROR-Dokumentation (Hervorhebung meiner):

Schweregrade von 0 bis 18 können von jedem Benutzer angegeben werden. Schweregrade von 19 bis 25 können nur von Mitgliedern der festen Serverrolle sysadmin oder Benutzern mit ALTER TRACE-Berechtigungen angegeben werden. Für Schweregrade von 19 bis 25 ist die Option WITH LOG erforderlich.

Es ist sehr wahrscheinlich, dass der Principal, den Sie ausführen, diese Kriterien nicht erfüllt.

Es ist nichts falsch daran, RAISERROR zu verwenden; Sie verwenden nur einen übermäßigen Schweregrad. Ich verwende Level 16 als Standard für einen Fehler, der ausgelöst wird und die Sequenz wird beendet. Wenn Sie genauer sein möchten, können Sie die von Microsoft selbst angegebenen Werte befolgen:

enter image description here

Nachdem dies alles gesagt wurde, reicht es je nach Kontext des Skripts möglicherweise nicht aus, RAISERROR zu verwenden, da das Skript nicht selbst "beendet" wird (unter Verwendung normaler Schweregrade).

Zum Beispiel:

RAISERROR(N'Test', 16, 1);

SELECT 1;   /* Executed! */

Dies wird beide einen Fehler auslösen und eine Ergebnismenge zurückgeben.

Um das Skript sofort zu beenden, bevorzuge ich die Verwendung von RETURN (Konstrukte vom Typ GOTO werden in den meisten Programmierkreisen, in denen Alternativen existieren, generell nicht empfohlen):

RAISERROR(N'Test', 16, 1);
RETURN;

SELECT 1;   /* Not executed */

Oder behandeln Sie den Fehler mit TRY/CATCH , wodurch die Ausführung zum Block CATCH springt, wenn der Schweregrad 11 oder höher ist:

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

Ein separates Problem besteht darin, dass das Skript mehrere Stapel umfasst - RETURN beendet nur den Stapel:

RAISERROR(N'Test', 16, 1);
RETURN;

SELECT 1;   /* Not executed */
GO

SELECT 2;   /* Executed! */

Um dies zu beheben, können Sie @@ERROR zu Beginn jeder Charge:

RAISERROR(N'Test', 16, 1);
RETURN;

SELECT 1;   /* Not executed */
GO

IF (@@ERROR != 0)
    RETURN;

SELECT 2;   /* Not executed */

Bearbeiten: Wie Martin Smith in den Kommentaren richtig hervorhebt, funktioniert dies nur für 2 Chargen. Um auf 3 oder mehr Stapel zu erweitern, können Sie solche Fehler kaskadieren (Hinweis: Die Methode GOTO löst dieses Problem nicht, da das Zieletikett innerhalb des Stapels definiert werden muss):

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 */

Oder, wie er auch betont, können Sie die SQLCMD -Methode verwenden, wenn dies für Ihre Umgebung geeignet ist.

8
Jon Seigel

Sie können die Anweisung GOTO verwenden, um zu überspringen, wo immer Sie möchten. Mit anderen Worten, Sie stoßen auf einen Fehler oder eine andere Bedingung, und am unteren Rand des Skripts befindet sich möglicherweise eine Bezeichnung (d. H. TheEndOfTheScript:) und geben Sie einfach ein goto TheEndOfTheScript; Aussage.

Hier ist ein kurzes Beispiel:

print 'here is the first statement...';

print 'here is the second statement...';

-- substitute whatever conditional flow determining factor
-- you'd like here. I have chosen a dummy statement that will
-- always return true
--
if (1 = 1)
    goto TheEndOfTheScript;

print 'here is the third statement...';

print 'here is the fourth statement...';


TheEndOfTheScript:
print 'here is the end of the script...';

Die Ausgabe dieser Ausführung lautet wie folgt:

here is the first statement...
here is the second statement...
here is the end of the script...

Wie Sie sehen können, hat GOTO das Drucken der dritten und vierten Anweisung übersprungen und ist direkt zum Etikett gesprungen (TheEndOfTheScript).

6
Thomas Stringer
4
Yogesh

Stimmen Sie mit dem SET NOEXEC ON/OFF, jedoch verwende ich in gespeicherten Prozessen (die einen einzelnen Block enthalten) einfach die Anweisung RETURN.

Vorsichtsmaßnahmen: Wenn Sie in einer Skriptdatei mehrere GO -Anweisungen haben, wird das RETURN nur aus dem aktuellen Block entfernt und mit dem nächsten Block/Stapel fortgesetzt.

Hinweis: GOTO soll eine schlechte Codierungspraxis sein, die Verwendung von "TRY..CATCH "wird empfohlen, da es seit SQL Server 2008 eingeführt wurde, gefolgt von THROW im Jahr 2012.

0
Eddie Kumar