Existe-t-il une commande dans Microsoft SQL Server T-SQL pour indiquer au script d'arrêter le traitement? J'ai un script que je souhaite conserver à des fins d'archivage, mais je ne veux pas que quiconque l'exécute.
Une autre solution pourrait être de modifier le flux d'exécution de votre script en utilisant l'instruction GOTO
...
DECLARE @RunScript bit;
SET @RunScript = 0;
IF @RunScript != 1
BEGIN
RAISERROR ('Raise Error does not stop processing, so we will call GOTO to skip over the script', 1, 1);
GOTO Skipper -- This will skip over the script and go to Skipper
END
PRINT 'This is where your working script can go';
PRINT 'This is where your working script can go';
PRINT 'This is where your working script can go';
PRINT 'This is where your working script can go';
Skipper: -- Don't do nuttin!
Attention! L'échantillon ci-dessus est dérivé d'un exemple que j'ai obtenu de Merrill Aldrich. Avant d'implémenter aveuglément l'instruction GOTO
, je vous recommande de lire son tutoriel sur Contrôle de flux dans les scripts T-SQL .
Non, il n'y en a pas - vous avez deux options:
Enveloppez le script entier dans un grand bloc if/end qui est simplement garanti de ne pas être vrai (c'est-à-dire "si 1 = 2 commence" - cela ne fonctionnera cependant que si le script ne comprend aucune instruction GO (car celles-ci indiquent un nouveau lot)
Utilisez l'instruction de retour en haut (là encore, limitée par les séparateurs de lots)
Utilisez une approche basée sur la connexion, qui garantira la non-exécution de l'ensemble du script (toute la connexion pour être plus précis) - utilisez quelque chose comme 'SET PARSEONLY ON' ou 'SET NOEXEC ON ' en haut du script. Cela garantira que toutes les instructions dans la connexion (ou jusqu'à ce que ladite instruction set soit désactivée) ne s'exécutent pas et seront à la place analysées/compilées uniquement.
Utilisez un bloc de commentaires pour commenter l'intégralité du script (c'est-à-dire/* et * /)
EDIT: Démonstration que l'instruction 'return' est spécifique au lot - notez que vous continuerez à voir les jeux de résultats après les retours:
select 1
return
go
select 2
return
select 3
go
select 4
return
select 5
select 6
go
Pourquoi ne pas simplement ajouter ce qui suit au début du script
PRINT 'INACTIVE SCRIPT'
RETURN
Pour contourner le problème RETURN/GO, vous pouvez placer RAISERROR ('Oi! Stop!', 20, 1) WITH LOG
en haut.
Cela fermera la connexion client selon RAISERROR sur MSDN .
Le très gros inconvénient est que vous devez être administrateur système pour utiliser la gravité 20.
Modifier:
Une simple démonstration pour contrer le commentaire de Jersey Dude ...
RAISERROR ('Oi! Stop!', 20, 1) WITH LOG
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
SELECT 'Will not run'
GO
RAISERROR de gravité 20 sera signalé comme une erreur dans l'Observateur d'événements.
Vous pouvez utiliser SET PARSEONLY ON; (ou NOEXEC). À la fin du script, utilisez GO SET PARSEONLY OFF;
SET PARSEONLY ON;
-- statement between here will not run
SELECT 'THIS WILL NOT EXEC';
GO
-- statement below here will run
SET PARSEONLY OFF;
Essayez de l'exécuter en tant que script TSQL
SELECT 1
RETURN
SELECT 2
SELECT 3
Le retour met fin à l'exécution.
Quitte inconditionnellement une requête ou une procédure. RETURN est immédiat et complet et peut être utilisé à tout moment pour quitter une procédure, un lot ou un bloc d'instructions. Les instructions qui suivent RETURN ne sont pas exécutées.
Voici une façon quelque peu délicate de le faire qui fonctionne avec des lots GO, en utilisant une variable "globale".
if object_id('tempdb..#vars') is not null
begin
drop table #vars
end
create table #vars (continueScript bit)
set nocount on
insert #vars values (1)
set nocount off
-- Start of first batch
if ((select continueScript from #vars)=1) begin
print '1'
-- Conditionally terminate entire script
if (1=1) begin
set nocount on
update #vars set continueScript=0
set nocount off
return
end
end
go
-- Start of second batch
if ((select continueScript from #vars)=1) begin
print '2'
end
go
Et voici la même idée utilisée avec une transaction et un bloc try/catch pour chaque GO-batch. Vous pouvez essayer de changer les différentes conditions et/ou le laisser générer une erreur (diviser par 0, voir commentaires) pour tester son comportement:
if object_id('tempdb..#vars') is not null
begin
drop table #vars
end
create table #vars (continueScript bit)
set nocount on
insert #vars values (1)
set nocount off
begin transaction;
-- Batch 1 starts here
if ((select continueScript from #vars)=1) begin
begin try
print 'batch 1 starts'
if (1=0) begin
print 'Script is terminating because of special condition 1.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
print 'batch 1 in the middle of its progress'
if (1=0) begin
print 'Script is terminating because of special condition 2.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
set nocount on
-- use 1/0 to generate an exception here
select 1/1 as test
set nocount off
end try
begin catch
set nocount on
select
error_number() as errornumber
,error_severity() as errorseverity
,error_state() as errorstate
,error_procedure() as errorprocedure
,error_line() as errorline
,error_message() as errormessage;
print 'Script is terminating because of error.'
update #vars set continueScript=0
set nocount off
return
end catch;
end
go
-- Batch 2 starts here
if ((select continueScript from #vars)=1) begin
begin try
print 'batch 2 starts'
if (1=0) begin
print 'Script is terminating because of special condition 1.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
print 'batch 2 in the middle of its progress'
if (1=0) begin
print 'Script is terminating because of special condition 2.'
set nocount on
update #vars set continueScript=0
set nocount off
return
end
set nocount on
-- use 1/0 to generate an exception here
select 1/1 as test
set nocount off
end try
begin catch
set nocount on
select
error_number() as errornumber
,error_severity() as errorseverity
,error_state() as errorstate
,error_procedure() as errorprocedure
,error_line() as errorline
,error_message() as errormessage;
print 'Script is terminating because of error.'
update #vars set continueScript=0
set nocount off
return
end catch;
end
go
if @@trancount > 0 begin
if ((select continueScript from #vars)=1) begin
commit transaction
print 'transaction committed'
end else begin
rollback transaction;
print 'transaction rolled back'
end
end
Malgré sa description très explicite et énergique, RETURN n'a pas fonctionné pour moi dans une procédure stockée (pour ignorer l'exécution ultérieure). J'ai dû modifier la logique des conditions. Se produit sur SQL 2008, 2008 R2:
create proc dbo.prSess_Ins
(
@sSessID varchar( 32 )
, @idSess int out
)
as
begin
set nocount on
select @id= idSess
from tbSess
where sSessID = @sSessID
if @idSess > 0 return -- exit sproc here
begin tran
insert tbSess ( sSessID ) values ( @sSessID )
select @idSess= scope_identity( )
commit
end
devait être changé en:
if @idSess is null
begin
begin tran
insert tbSess ( sSessID ) values ( @sSessID )
select @idSess= scope_identity( )
commit
end
Découvert suite à la recherche de lignes dupliquées. Le débogage des PRINT a confirmé que @idSess avait une valeur supérieure à zéro dans la vérification IF - RETURN n'a pas interrompu l'exécution!
Je sais que la question est ancienne et a été répondue correctement de différentes manières, mais il n'y a pas de réponse comme la mienne que j'ai utilisée dans des situations similaires. Première approche (très basique):
IF (1=0)
BEGIN
PRINT 'it will not go there'
-- your script here
END
PRINT 'but it will here'
Deuxième approche:
PRINT 'stop here'
RETURN
-- your script here
PRINT 'it will not go there'
Vous pouvez le tester facilement par vous-même pour vous assurer qu'il se comporte comme prévu.