Область переменных, которые определены в блоке while в хранимых процедурах - SQl Server
Я нашел интересный сценарий (по крайней мере для меня) в хранимой процедуре. Хотелось бы иметь мнение экспертов и мысли об этом.
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_ _
Вместо этого я получил вывод, как показано ниже:
Value_10 _
Value_10 _
Value_8 _
Value_8 _
Value_6 _
Value_6 _
Value_4 _
Value_4 _
значение_2 _
значение_2 _
Я думал, что если объявить переменную внутри блока while, то для каждой итерации она будет reset значением NULL или значением по умолчанию (из фона С#).
Если это по дизайну, то мой вопрос в том, как SQLServer обрабатывает оператор DECLARE для этой переменной внутри блока? Не игнорирует ли он это, поскольку переменная уже находится в памяти?
Может кто-нибудь, пожалуйста, объясните мне это поведение? Пожалуйста, со мной, если ты обнаружишь, что это глупо. Я все еще участвую:)
Обновление: Спасибо всем за примеры и объяснения. Сегодня вы заставили меня узнать новое.
Ответы
Ответ 1
Область переменной - это целая партия в этом случае хранимая процедура.
Он не повторно объявляется в каждом цикле
Итак, это точно так, как ожидалось
Изменить:
Существует недавняя статья статьи в блоге, которая очень похожа. Автор был быстро исправлен: -)
Ответ 2
От Переменные Transact-SQL
Объем переменной - это диапазон операторов Transact-SQL, которые может ссылаться на переменную. Объем переменной длится от указывает, что он объявлен до конца партии или хранимой процедуры в который он объявлен.
DECLARE
сам по себе не является исполняемым. Все объявления переменной идентифицируются во время компиляции и зарезервированная для них память в контексте выполнения.
Если вы используете синтаксис Declare и Set 2008+. Тем не менее, для части цикла будет выполняться каждая итерация цикла.
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
Ответ 3
Попробуйте это для удовольствия
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
Ответ 4
От Объявить:
Область локальной переменной - это пакет, в котором он объявлен.
В T-SQL больше нет "локальных" правил определения области видимости. Это также означает, что вы не можете объявить одно и то же имя переменной внутри блоков IF и ELSE.
Все Declare does объявляет переменную. Он не имеет никакого отношения к назначению. Значение любой переменной, которая никогда не была назначена, равна NULL
. Но после этого единственный способ, когда значение переменных станет NULL
снова, - через явное назначение.
Если вам нужно, чтобы он был NULL
в верхней части каждой итерации цикла, поэтому вы должны явно назначить его.
Ответ 5
В T-SQL a WHILE..END
не является индивидуально областью, вы можете, например, SELECT @insidevalue
после WHILE
END
.
Ответ 6
DECLARE @loopcounter INT
SET @loopcounter=10
WHILE @loopcounter > 0
BEGIN
DECLARE @insidevalue int
IF (@loopcounter%2 = 0)
begin
set @[email protected]
PRINT 'Value_' + CAST(@insidevalue AS NVARCHAR) + '_'
end
ELSE
PRINT 'Value_' + ' ' + '_'
SET @loopcounter = @loopcounter - 1
END
Ответ 7
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