SQL Server 2012のストアドプロシージャで、いくつかの入れ子構造があります。それらの単層から抜け出したいです。
MsdnのBREAKの説明 https://msdn.Microsoft.com/en-CA/library/ms181271.aspx が私の側にあると思いました。しかし、デバッグのシングルステップで実行しているときに、奇妙な動作が発生します。それは一貫していないので、私は奇妙に言います。時にはそれは私が期待する層にエスケープします。時々それはカップルをスキップします。
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
したがって、NumberRecords = 0の場合、次の操作はif at stuff6になるはずですよね?たとえば、stuff4に、EXEC呼び出しからストアドプロシージャへのINSERT INTOテーブルが含まれている場合でも、レイヤーからスタックを混乱させることができるものはありませんか?
そして、はい、私はそれが醜いSQLであることを理解しています。ほとんどの命令は2つの一時テーブルの編集であり、そうでなければコードをクリーンアップするストアドプロシージャにそれらをやり取りすることを避けていました。
[〜#〜]編集[〜#〜]
最初にブレークアウトしたい内部IFの周りにダミーのWHILEループを追加することで、希望どおりのルートを確保することができました。しかし、私は本当に私がmsdn情報を誤って解釈しているのか知りたいです。 ENDステートメントがある限り、BREAKはIFから抜け出す必要があると思われます。
出口 wHILEステートメントの最も内側のループ または、WHILEループ内のIF…ELSEステートメント。 ENDキーワードの後に出現し、ループの終わりを示すステートメントが実行されます。
ドキュメント は少しわかりにくいことに同意します。この行は、IFを中断できることを示唆しているようです。
WHILEステートメント内の最も内側のループまたはWHILEループ内のIF…ELSEステートメントを終了します。 ENDキーワードの後に出現し、ループの終わりを示すステートメントが実行されます。 BREAKは、必ずというわけではありませんが、IFテストによって開始されます。
しかし、そうではありません。 BREAKは、その位置から最も内側のWHILEを終了します。ドキュメントの重要な部分は、「ループの終わりを示すENDキーワードの後に続くステートメントが実行される」です。
この例はこれを示しています。
例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'
開始テキストと終了テキストのみが印刷されます。 BREAKはWHILEが存在するため、1は出力されません。
この動作はここでも確認できます。
例2
/* Anti-Pattern.
* Breaking outside a WHILE is not allowed.
*/
IF 1 = 1
BEGIN
BREAK
PRINT 1
END
このクエリはエラーを返します:
メッセージ135、レベル15、状態1、行4 WHILEステートメントのスコープ外ではBREAKステートメントを使用できません。
上記の例のように、 "Start、1、End"を出力するためにIFステートメントから抜け出したい場合は、次のようにします。
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'
これを使用して、以下を使用してOPの例を処理できますが
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
これは一般的に、ブール論理を逆にするためのより良いアプローチと考えられています。例えば:
IF NOT @NumberRecords=0
BEGIN
stuff5
END