Подтвердить что ты не робот

SQL назначить переменную с подзапросом

У меня есть вопрос для следующих двух SQL:

declare @i1 bit, @b1 bit
declare @i2 bit, @b2 bit
declare @t table (Seq int)
insert into @t values (1)

-- verify data
select case when (select count(1) from @t n2 where 1 = 2) > 0 then 1 else 0 end
-- result 0

select @i1 = 1, @b1 = case when @i1 = 1 or ((select count(1) from @t n2 where 1 = 2) > 0) then 1 else 0 end from @t n where n.Seq = 1
select @i1, @b1
-- result 1, 0

select @i2 = 1, @b2 = case when @i2 = 1 or (0 > 0) then 1 else 0 end from @t n where n.Seq = 1
select @i2, @b2
-- result 1, 1

SQL Fiddle Here

Перед выполнением я подумал, что часть корпуса должна быть null = 1 or (0 > 0), и она вернет 0.

Но теперь я задаюсь вопросом, почему второй SQL вернет 1

4b9b3361

Ответ 1

Я отправлю это как ответ, так как это довольно большой текст из Training Kit (70-461):

WHERE propertytype = 'INT' AND CAST(propertyval AS INT) > 10

Некоторые полагают, что, если правила приоритета не диктуют иначе, предикаты будет оцениваться слева направо, и это короткое замыкание будет если возможно. Другими словами, если первый предикат propertytype = 'INT' оценивает значение false, SQL Server не оценивает второй предикат CAST (propertyval AS INT) > 10, потому что результат Уже известно. Исходя из этого предположения, ожидается, что запрос никогда не должен пытаться конвертировать то, что не является кабриолет.

Реальность, однако, различна. SQL Server делает внутренняя поддержка концепции короткого замыкания; однако, из-за концепция "все-в-одном" на языке, это необязательно оцените выражения в порядке слева направо. Он мог решить, основанные на связанных с затратами причинах, начать со второго выражения, а затем, если второе выражение оценивается как true, для оценки первое выражение. Это означает, что если в строке есть строки table, где propertytype отличается от "INT", а в тех строках propertyval не конвертируется в INT, запрос может завершиться неудачно из-за ошибка преобразования.

Ответ 2

Просто чтобы продлить ответ @Giorgi:

Смотрите этот план выполнения: Концепция оптимизации Поскольку @i2 оценивается сначала (@i2 = 1), case when @i2 = 1 or anything возвращает 1.

См. также эту запись msdn: https://msdn.microsoft.com/en-us/library/ms187953.aspx и раздел "Предостережение"

Если в одной инструкции SELECT имеется несколько предложений предложения, SQL Server не гарантирует порядок оценки выражения. Обратите внимание, что эффекты видны только в том случае, если есть ссылки между назначениями.

Все это связано с внутренней оптимизацией.

Ответ 3

Просто чтобы расширить оба ответа.

От Грязные секреты выражения CASE:

CASE не всегда будет короткое замыкание

Официальная документация подразумевает, что все выражение будет короткозамкнутым, что означает, что он будет оценивать выражение слева направо и перестает оценивать, когда он попадает в совпадение:

The CASE statement  evaluates its conditions sequentially and stops with the
first condition whose condition is satisfied.

И MS Connect:

CASE Transact-SQL

Оператор CASE последовательно оценивает свои условия и останавливается с первым условием, условие которого выполняется. В некоторых ситуациях выражение оценивается до того, как оператор CASE получает результаты выражения в качестве своего ввода. Возможны ошибки при оценке этих выражений.