SQL Server: comment annuler une série de lots dans L'Analyseur de requêtes?

j'ai une série de déclarations T-SQL séparées par le mot-clé du séparateur par lots de L'Analyseur de requêtes spécial:

GO

si un lot échoue, j'ai besoin D'un analyseur de requête pour ne pas essayer les lots suivants - je veux qu'il arrête le traitement de la série de lots.

par exemple:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go

PRINT 'This should not run'
go

sortie:

This runs
Server: Msg 8134, Level 16, State 1, Line 2
Divide by zero error encountered.
This should not run

Possible?


mise à Jour

un exemple d'utilisation réelle pourrait être:

 sp_rename 'Shelby', 'Kirsten'
 go

 DROP VIEW PeekAView
 go

 CREATE VIEW PeekAViewAS 
 SELECT * FROM Kirsten
 go
4
demandé sur divibisan 2009-05-29 21:08:58

6 réponses

Voici comment je le ferais:

PRINT 'This runs'
go

SELECT 0/0, 'This causes an error'
go
if (@@error <> 0)
    Begin
    set nocount on
    set noexec on
    End
GO

PRINT 'This should not run'
go

set noexec off
set nocount off
GO

le mode "noexec" puts SSMS est un état où il compile le T-SQL et ne l'exécute pas. Il est similaire à appuyer accidentellement sur le bouton Parse toolbar (Ctrl+F5) au lieu d'exécuter (F5).

n'oubliez pas de désactiver noexec à la fin de votre script. Sinon, les utilisateurs vont être confus par "commande(s) permanente (s) terminée (s) avec succès." message.

j'utilise le contrôle contre l'erreur @@dans le lot suivant au lieu d'utiliser des blocs de capture D'essai. L'utilisation de @@error dans le prochain lot attrapera des erreurs de compilation, comme "table doesn't exist".

en plus du mode noexec, je bascule aussi le mode nocount. Avec le mode noexec activé et le mode nocount désactivé, vos requêtes feront quand même état d'un message "(0 ligne(s) touchée (s))". Le message indique toujours zéro ligne, parce que vous êtes en mode noexec. Cependant, en tournant le compte de nuit sur les suppressions ces messages.

notez aussi que si vous exécutez SQL Server 2005, la commande que vous sautez peut encore donner des messages d'erreur si elle renvoie à une table qui n'existe pas et la commande si la première commande dans le lot. Forcer la commande à être la deuxième commande dans le lot avec une fausse déclaration D'impression peut supprimer cela. Voir ms Bug # 569263 pour plus de détails.

7
répondu Timothy Klenke 2012-05-23 06:46:52

vous pouvez activer l'option de menu "Requête, mode SQLCMD" et placer ce qui suit Au début du script:

:on error exit

ceci stoppera l'exécution lorsqu'une erreur se produit, même s'il y a des lots ultérieurs.

assurez-vous simplement de ne pas lancer accidentellement le script sans le mode SQLCMD car vous obtiendrez le comportement typique où les erreurs sont ignorées.

4
répondu Jason Kresowaty 2009-10-13 02:41:39

quand j'ai besoin de faire ça, j'émets une RAISERROR de sévérité 20. Ceci, ou plus, supprimera la connexion courante, et empêchera les "lots de GO" ultérieurs de s'exécuter. Oui, ça peut être gênant, mais ça fait l'affaire.

2
répondu Philip Kelley 2009-10-13 02:52:45

créer une table temporaire; et la mettre à jour après chaque étape (si réussie); et puis vérifier le succès de l'étape précédente en validant par rapport à la table.

create table #ScriptChecker (SuccessfullStep int)

-- Do Step One
Insert into #ScriptChecker
Select 1

-- Step 2
If exists (select * from #ScriptChecker where SuccessfullStep = 1)
-- Do Step 2 ...
1
répondu u07ch 2009-05-29 17:15:53

basé sur l'idée de @u07ch, mais insérez seulement en cas de panne...

create table #test (failure  int)

if not exists (select * from #test)
BEGIN
    print 'one' --sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'two'--sql here
END
go

if not exists (select * from #test)
BEGIN
    print 'three' ---SQL SERVER 2000 version
    --error--
    SELECT 0/0, 'This causes an error'
    IF @@ERROR!=0
    BEGIN
        insert into #test values (1)
        PRINT 'ERROR'
    END
end 
go

if not exists (select * from #test)
BEGIN
    print 'three'  ---SQL SERVER 2005/2008 version
    BEGIN TRY
    --error--
        SELECT 0/0, 'This causes an error'
    END TRY
    BEGIN CATCH
        insert into #test values (1)
        PRINT 'ERROR'
    END CATCH
END
go

if not exists (select * from #test)
BEGIN
    --sql here
    print 'four'
END
go

sortie 2000:

one
two
three

----------- --------------------
Msg 8134, Level 16, State 1, Line 7
Divide by zero error encountered.

(1 row(s) affected)

ERROR

sortie 2005/2008:

one
two
three

----------- --------------------

(0 row(s) affected)

(1 row(s) affected)

ERROR
1
répondu KM. 2009-05-29 18:00:06

Erland Sommarskog dans le microsoft.public.sqlserver.groupe de programmation avait une très bonne idée:

dans un script de changement comme celui que vous posté, vous devez être sur la défensive, et commencez chaque lot avec SI @@trancount > 0.

utilisant

IF @@trancount > 0 

est beaucoup plus propre.

0
répondu Ian Boyd 2009-06-03 18:13:51