SQL-оператор «Или».Как это работает в следующем сценарии?

StackOverflow https://stackoverflow.com/questions/473943

Вопрос

Я работал над оптимизацией запроса и столкнулся с ситуацией, которая заставляет меня задаться вопросом, как я всегда использовал оператор OR SQL.(также SQL Server 2000)

У меня есть запрос, в котором условное предложение (WHERE) выглядит примерно так:

WHERE (Column1 = @Param1 or Column1 LIKE @Param1 + '%')
AND (@Param2 = '' OR Column2 = @Param2 OR Column2 LIKE @Param2 + '%')

Я всегда понимал, что OR в SQL оценивает оба выражения.Таким образом, все записи, которые получили истинное значение для левого выражения, будут возвращены вместе со всеми записями, которые получили истинное значение для правого выражения.Например:

SELECT * FROM TABLE1
WHERE COL1 = 'Test' OR Col2 = 'Data'

Это вернет обратно все записи, где COL1 — «Тест», а также любую запись, где Col2 — «Данные».

В приведенном выше примере я изменил условие Column2 следующим образом:

AND(Column2 LIKE ISNULL(@Param2, '') + '%')

Внезапно я получаю 0 строк.

Ошибся ли я в том, что OR оценивает выражения только до тех пор, пока не найдет результат TRUE, или существует условие, при котором два разных выражения будут возвращать разные результаты?

Это было полезно?

Решение

«ИЛИ оценивает выражения только до тех пор, пока не найдет результат ИСТИНА»

Это просто необходимо, но это не ваша проблема (собственно, именно это вас и спасало в вашем исходном случае).Ваши два запроса на самом деле не эквивалентны.

Я думаю, у тебя есть NULLs в столбце 2, который никогда не вызовет (Column2 LIKE ISNULL(@Param2, '') + '%') чтобы быть правдой - и в вашей исходной версии @Param2 = '' скрывал этот случай, поскольку это правда (иногда)

Возможно:

(ISNULL(Column2, '') LIKE ISNULL(@Param2, '') + '%')

Помните трехзначную логику для NULL:

TRUE and UNKNOWN: UNKNOWN
TRUE or UNKNOWN: TRUE

FALSE and UNKNOWN: FALSE
FALSE or UNKNOWN: UNKNOWN

Но я не уверен, что ваша оптимизация действительно помогает.

Другие советы

OR не является всеобъемлющим, особенно потому, что он заключен в круглые скобки.В большем размере у вас есть: WHERE X AND Y.Тот факт, что X и Y сами по себе являются логическими выражениями, использующими ИЛИ, не важен:они оцениваются отдельно, а затем результаты передаются оператору AND.

[редактировать]:
Прочитав еще раз, возможно, я неправильно понял ваш вопрос.Имея это в виду, мне придется выбрать другой ответ, потому что NULL LIKE '%' возвращает NULL, что в данном случае равно false.Вместо этого вы можете попробовать это:

COALESCE(Column2,'') LIKE COALESCE(@param2,'') + '%'

К вашему сведению, вы можете провести очень простые эксперименты, чтобы убедиться, что не все условия обязательно оценены.

Я сделал это в Oracle, но я ожидаю, что у вас будет аналогичный результат в SQL Server.

dev> select * from dual where 1=1 or 1/0 = 3;

D
-
X

Условие после ИЛИ не должно оцениваться, так как это приведет к ошибке деления на ноль.

Такая обработка булевых операторов обычно известна как " короткое замыкание " и, AFAIK, является довольно стандартным в современных языках. Это также может применяться в выражении AND - если первое условие ложно, нет смысла оценивать второе условие, поскольку все выражение не может быть ИСТИНОЙ.

Дополнительная информация: http://en.wikipedia.org/wiki/Short-circuit_evaluation

В любом случае, как сказал Кейд, ваша настоящая проблема, вероятно, в неправильном обращении с NULL.

MS-SQL сначала оценит левую часть и не будет продолжать, если в этом нет необходимости.

То же самое и с соединителем AND, левая сторона будет оценена, а если ложь, то правая не будет оценена.

scroll top