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