Dans une procédure stockée SQL Server 2012, j'ai plusieurs structures imbriquées. Je veux sortir d'une seule couche d'entre eux.
Je pensais que la description de BREAK dans le msdn https://msdn.Microsoft.com/en-CA/library/ms181271.aspx était de mon côté. Mais j'obtiens un comportement étrange en l'exécutant en une seule étape via le débogage. Je dis étrange parce que ce n'est pas cohérent. Parfois, il échappe à la couche que je m'attends .. parfois, il saute un couple.
WHILE ... BEGIN
stuff1
IF...BEGIN
stuff2
WHILE ... BEGIN
stuff3
IF .... BEGIN
stuff4
IF @NumberRecords=0 BREAK
stuff5
END
--stuff6
if @NumberRecords=0 and @loopBOMRowCount=@ResultsSOloopstart-1 break
--on the last occasion I observed, @loopBOMRowCount was 6 and @ResultsSOloopstart 71 and it never highlighted this section, either way
SET @loopBOMRowCount = @loopBOMRowCount + 1
END
stuff7 --nothing actually here
END
--stuff8
SET @periodloopcount=@periodloopcount+1
--this is where it ended up highlighting on that last occasion
END
stuff9
Donc, si NumberRecords = 0, alors la prochaine opération devrait être la suivante: if at stuff6, non? Même si stuff4 inclut, par exemple, une table INSERT INTO d'un appel EXEC à une procédure stockée? Rien ne devrait pouvoir confondre la pile de ses couches?
Et oui, je réalise que c'est du vilain SQL. La plupart des instructions sont des modifications sur deux tables temporaires et j'évitais de les transmettre à des procédures stockées qui autrement nettoieraient le code.
EDIT
J'ai réussi à le faire passer comme je le voulais en ajoutant une boucle WHILE factice autour du SI intérieur, je veux commencer par le premier. Mais j'aimerais vraiment savoir comment j'interprète mal l'info msdn. Il semble dire qu'une pause doit sortir d'un SI, à condition qu'elle contienne une instruction END.
Sorties la boucle la plus interne dans une instruction WHILE ou une instruction IF… ELSE dans une boucle WHILE. Toutes les instructions apparaissant après le mot clé END, marquant la fin de la boucle, sont exécutées.
Je conviens que la documentation est un peu déroutante. Cette ligne semble suggérer que vous pouvez SORTIR d’un IF.
Quitte la boucle la plus interne dans une instruction WHILE ou une instruction IF… ELSE dans une boucle WHILE. Toutes les instructions apparaissant après le mot clé END, marquant la fin de la boucle, sont exécutées. BREAK est fréquemment, mais pas toujours, démarré par un test IF.
Cependant, ce n'est pas le cas. BREAK quitte le plus intérieur de sa position. La partie clé de la documentation est "toutes les instructions apparaissant après le mot-clé FIN, marquant la fin de la boucle , sont exécutées".
Cet exemple montre cela.
Exemple 1
DECLARE @X INT = 1;
PRINT 'Start'
/* WHILE loop required to use BREAK.
*/
WHILE @X = 1
BEGIN
/* Outer IF.
*/
IF 1 = 1
BEGIN
/* Inner IF.
*/
IF 2 = 2
BEGIN
BREAK
PRINT '2'
END
PRINT '1'
END
SET @X = @X + 1;
END
PRINT 'End'
Seul le texte de début et de fin est imprimé. 1 n'est pas imprimé parce que BREAK existe et WHILE.
Vous pouvez également voir ce comportement ici:
Exemple 2
/* Anti-Pattern.
* Breaking outside a WHILE is not allowed.
*/
IF 1 = 1
BEGIN
BREAK
PRINT 1
END
Cette requête renvoie l'erreur:
Msg 135, niveau 15, état 1, ligne 4 Impossible d'utiliser une instruction BREAK en dehors du cadre d'une instruction WHILE.
Si vous voulez vraiment vous échapper de la déclaration SI, imprimez "Démarrer, 1, Fin" comme dans l'exemple ci-dessus, procédez comme suit:
DECLARE @X INT = 1;
PRINT 'Start'
/* WHILE loop required to use BREAK.
*/
WHILE @X = 1
BEGIN
/* Outer IF.
*/
IF 1 = 1
BEGIN
/* Inner IF.
*/
IF 2 = 2
BEGIN
GOTO skip2
PRINT '2'
END
skip2:
PRINT '1'
END
SET @X = @X + 1;
END
PRINT 'End'
Maintenant, alors que vous pourriez utiliser cela pour gérer l'exemple du PO en utilisant ce qui suit
WHILE ... BEGIN
stuff1
IF...BEGIN
stuff2
WHILE ... BEGIN
stuff3
IF .... BEGIN
stuff4
IF @NumberRecords=0
GOTO startstuff6
stuff5
END
startstuff6:
--stuff6
if @NumberRecords=0 and @loopBOMRowCount=@ResultsSOloopstart-1
GOTO startstuff7
--on the last occasion I observed, @loopBOMRowCount was 6 and @ResultsSOloopstart 71 and it never highlighted this section, either way
SET @loopBOMRowCount = @loopBOMRowCount + 1
END
startstuff7:
stuff7 --nothing actually here
END
--stuff8
SET @periodloopcount=@periodloopcount+1
--this is where it ended up highlighting on that last occasion
END
stuff9
Il est généralement considéré comme une meilleure approche d'inverser votre logique booléenne, par exemple:
IF NOT @NumberRecords=0
BEGIN
stuff5
END