ストアドプロシージャで(少なくとも私にとっては)興味深いシナリオに遭遇しました。それについて専門家の意見や考えを持ちたい。
DECLARE @loopcounter INT
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
DECLARE @insidevalue int
IF (@loopcounter%2 = 0)
SET @insidevalue = @loopcounter
PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'
SET @loopcounter = @loopcounter - 1
END
このブロックが以下のような出力を与えると期待していました
Value_10_ Value_ _ Value_8_ Value_ _ Value_6_ Value_ _ Value_4_ Value_ _ Value_2_ Value_ _
代わりに、以下のように出力されました:
値_10_
値_10_
値_8_
値_8_
値_6_
値_6_
値_4_
値_4_
値_2_
値_2_
Whileブロック内で変数を宣言すると、反復ごとに値がNULLまたはデフォルト値(c#バックグラウンドから)にリセットされると思いました。
これが仕様による場合、私の質問は、SQLServerがブロック内のその変数の 'DECLARE'ステートメントをどのように処理するかです。変数はすでにメモリにあるので無視しますか?
誰かがこの動作を説明してくれませんか?
変数スコープは、この場合はストアドプロシージャのバッチ全体です。
ループごとに再宣言されるわけではありません
これは予想通りです
編集:
最近の ブログ記事 は非常によく似ています。著者はすぐに修正されました:-)
From Transact-SQL変数
変数のスコープは、変数を参照できるTransact-SQLステートメントの範囲です。変数のスコープは、変数が宣言された時点から、それが宣言されているバッチまたはストアドプロシージャの最後まで続きます。
DECLARE
自体は実行可能なステートメントではありません。変数宣言はすべて コンパイル時に識別 であり、実行コンテキストでそれらのために予約されているメモリです。
2008+ Declare and Set構文を使用する場合。ただし、ステートメントの設定部分はループの反復ごとに発生します。
DECLARE @loopcounter INT
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
DECLARE @insidevalue INT = NULL
IF (@loopcounter%2 = 0)
SET @insidevalue = @loopcounter
PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'
SET @loopcounter = @loopcounter - 1
END
これをお楽しみください
if 1 = 0
begin
-- will never happen
declare @xx int
end
else
begin
set @xx = 1
end
print @xx
明らかに、宣言コードを実行する必要はありません。使用前にのみ宣言してください。
これは機能しません
if 1 = 0
begin
-- will never happen
set @xx = 1
end
else
begin
declare @xx int
end
print @xx
から 宣言 :
ローカル変数のスコープは、それが宣言されているバッチです。
T-SQLには「ローカル」スコープルールはありません。また、IFおよびELSEブロック内で同じ変数名を宣言することはできません。
Declareが行うのは、変数をdeclareすることだけです。 assignmentとは関係ありません。割り当てられたことのない変数の値はNULL
です。しかし、その後、変数の値が再びNULL
になる唯一の方法は、明示的な割り当てによるものです。
したがって、各ループ反復の先頭でNULL
にする必要がある場合は、明示的に割り当てる必要があります。
T-SQLではWHILE..END
のスコープは個別ではありません。たとえば、SELECT @insidevalue
WHILE
のEND
の後。
DECLARE @loopcounter INT
DECLARE @insidevalue int
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
IF (@loopcounter%2 = 0)
BEGIN
SET @insidevalue = @loopcounter
PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'
END
ELSE
PRINT 'Value_'+' '+'_'
SET @loopcounter = @loopcounter - 1
END
多くの場合、整数データ型にはNULLの0しかありません
宣言文はループ内で毎回発生するわけではありません
なぜ使用しないのですか
DECLARE @loopcounter INT
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
IF @loopcounter%2 = 0
PRINT 'Value_' + CAST(@loopcounter AS NVARCHAR) + '_'
else
PRINT 'Value_ _'
SET @loopcounter = @loopcounter - 1
END
それは与える:
Value_10_
Value_ _
Value_8_
Value_ _
Value_6_
Value_ _
Value_4_
Value_ _
Value_2_
Value_ _
DECLARE @loopcounter INT
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
DECLARE @insidevalue int
IF (@loopcounter%2 = 0)
begin
set @insidevalue=@loopcounter
PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'
end
ELSE
PRINT 'Value_' + ' ' + '_'
SET @loopcounter = @loopcounter - 1
END