SQL Server-arrêt ou interruption de l'exécution D'un script SQL

y a-t-il un moyen d'arrêter immédiatement l'exécution D'un script SQL dans SQL server, comme une commande" break "ou" exit"?

j'ai un script qui fait quelques validations et recherches avant de commencer à faire des inserts, et je veux qu'il s'arrête si l'une des validations ou des recherches échoue.

272
demandé sur Blorgbeard 2009-03-18 20:04:20

18 réponses

Le raiserror méthode

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

ceci mettra fin à la connexion, empêchant ainsi le reste du script de fonctionner.

notez que le niveau de gravité 20 ou plus et l'option WITH LOG sont nécessaires pour qu'il fonctionne de cette façon.

cela fonctionne même avec les déclarations de GO, par exemple.

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

vous donnera la sortie:

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.

Remarquez que " ho " est pas imprimé.

mises en garde:

  • cela ne fonctionne que si vous êtes connecté en tant qu'administrateur (rôle'sysadmin'), et vous laisse également sans connexion à la base de données.
  • si vous n'êtes pas connecté en tant qu'administrateur, L'appel de RAISEERROR() échouera et le script continuera d'exécuter .
  • Lorsqu'il est invoqué avec sqlcmd.EXE, le code de sortie 2745 sera signalé.

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

la méthode noexec

une autre méthode qui fonctionne avec les instructions GO est set noexec on . Cela fait sauter le reste du script. Il ne met pas fin à la connexion, mais vous devez désactiver à nouveau noexec avant l'exécution de toute commande.

exemple:

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
répondu Blorgbeard 2017-07-18 16:43:00

il suffit d'utiliser un retour (il fonctionnera à la fois à l'intérieur et à l'extérieur d'une procédure stockée).

153
répondu Gordon Bell 2009-03-18 17:23:19

si vous pouvez utiliser le mode SQLCMD, alors l'incantation

:on error exit

(y compris le colon) va faire arrêter le script par RAISERROR. Par exemple,

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

sortira:

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

et le lot arrêter. Si le mode SQLCMD n'est pas activé, vous obtiendrez une erreur d'analyse sur le côlon. Malheureusement, ce n'est pas complètement à l'épreuve des balles comme si le script était exécuté sans être en mode SQLCMD, SQL Managment Le Studio brille juste après même les erreurs de temps! Quand même, si vous les faîtes sortir de la ligne de commande, c'est très bien.

41
répondu Sglasses 2010-04-07 06:13:39

Je n'utiliserais pas RAISERROR - SQL a si les déclarations qui peuvent être utilisées à cet effet. Faites vos recherches et validations et définissez des variables locales, puis utilisez la valeur des variables dans les instructions IF pour rendre les inserts conditionnels.

vous n'auriez pas besoin de vérifier un résultat variable de chaque test de validation. Vous pouvez généralement le faire avec une seule variable flag pour confirmer toutes les conditions passées:

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

même si votre validation est plus complexe, vous devriez seulement besoin d'un peu de drapeau des variables à inclure dans votre contrôle final(s).

20
répondu Dave Swersky 2012-05-17 11:24:33

vous pouvez envelopper votre instruction SQL dans une boucle WHILE et utiliser BREAK si nécessaire""

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
répondu Jon Erickson 2009-03-18 17:27:14

j'ai étendu la solution noexec on/off avec succès avec une transaction pour exécuter le script en tout ou rien.

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

apparemment le compilateur "comprend" la variable @finished dans le SI, même s'il y avait une erreur et que l'exécution était désactivée. Cependant, la valeur est définie à 1 seulement si l'exécution n'a pas été désactivée. Je peux donc engager ou annuler la transaction en conséquence.

11
répondu Tz_ 2011-10-25 12:27:31

en SQL 2012+, vous pouvez utiliser jeter .

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

de MSDN:

soulève une exception et transfère l'exécution à un bloc de capture D'un TRY...CATCH construction ... Si une construction TRY...CATCH n'est pas disponible, la session est terminée. Le numéro de ligne et la procédure où l'exception est soulevée sont définis. La sévérité est fixée à 16.

11
répondu Jordan Parker 2015-11-19 16:21:15

est-ce une procédure enregistrée? Si c'est le cas, je pense que vous pourriez simplement faire un retour, comme "Return NULL";

7
répondu mtazva 2009-03-18 17:07:52

Plus refinig Sglasses méthode, les lignes de force de l'utilisation de mode SQLCMD, et soit treminates le scirpt si vous n'utilisez pas le mode SQLCMD ou utilise des :on error exit à la sortie sur une erreur

CONTEXT_INFO est utilisé pour garder une trace de l'état.

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
répondu jaraics 2010-08-24 15:55:50

je vous suggère d'envelopper votre bloc de code approprié dans un bloc d'essai. Vous pouvez ensuite utiliser L'événement Raiserror avec une sévérité de 11 afin de casser au bloc catch si vous le souhaitez. Si vous voulez seulement raiserrors mais continuer l'exécution dans le bloc d'essai, utilisez une sévérité plus faible.

ça a un sens?

santé, John

[révisé pour inclure la référence BOL]

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

6
répondu John Sansom 2009-03-19 12:29:49

vous pouvez utiliser RAISERROR .

5
répondu Mladen Prajdic 2009-03-18 17:05:27

vous pouvez modifier le déroulement de l'exécution en utilisant GOTO instructions:

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

/* our code */

EndScript:
5
répondu Charlie 2016-12-09 15:21:25

aucun de ceux-ci ne fonctionne avec des déclarations de "GO". Dans ce code, peu importe si la gravité est 10 ou 11, Vous obtenez la déclaration finale D'impression.

Script De Test:

-- =================================
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

résultats:

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

la seule façon de faire ce travail est d'écrire le script sans les déclarations GO . Parfois, c'est facile. Il est parfois assez difficile. (Utilisez quelque chose comme IF @error <> 0 BEGIN ... .)

4
répondu Rob Garrison 2017-10-27 12:59:20

C'était ma solution:

...

BEGIN
    raiserror('Invalid database', 15, 10)
    rollback transaction
    return
END
3
répondu Casper Leon Nielsen 2012-06-27 08:40:44

vous pouvez utiliser la déclaration GOTO. Essayez ceci. C'est l'utilisation complet pour vous.

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

FinalStatement:
     Select @CoumnName from TableName
2
répondu Vishal Kiri 2015-09-07 06:58:18

Thx pour la réponse!

raiserror() fonctionne bien mais vous ne devriez pas oublier la déclaration return sinon le script continue sans erreur! (hense l'instruction raiserror n'est pas un "throwerror" ;-)) et, bien sûr, faire une restauration en cas de besoin!

raiserror() est agréable de dire à la personne qui exécute le script que quelque chose a mal tourné.

1
répondu 2009-03-31 13:52:18

si vous exécutez simplement un script dans Management Studio, et que vous voulez arrêter l'exécution ou la transaction de roll-back (si utilisée) sur la première erreur, alors la meilleure façon que je compte est d'utiliser le bloc de capture d'essai (SQL 2005 onward). Cela fonctionne bien dans Management studio si vous exécutez un fichier script. Procédure stockée peut toujours l'utiliser également.

1
répondu Bhargav Shah 2012-07-05 07:34:31

j'utilise RETURN ici tout le temps, travaille dans le script ou Stored Procedure

assurez-vous que vous ROLLBACK l'opération si vous êtes dans un, sinon RETURN immédiatement résultera en une opération ouverte non engagée

1
répondu jerryhung 2018-04-28 19:02:36