Эффективный способ сравнения для NULL или значения для столбца в SQL - PullRequest
9 голосов
/ 24 июня 2010

Какой эффективный способ проверить нулевое значение или значение для столбца в запросе SQL. Рассмотрим таблицу SQL table с целочисленным столбцом column, который имеет индекс. @value может быть целым или нулевым, например: 16 или нулевым.

Запрос 1: Не уверен, но, похоже, не следует полагаться на короткое замыкание в SQL. Однако приведенный ниже запрос всегда работает правильно, когда @value является некоторым целым числом или нулем.

select * from
table
where (@value is null or column = @value)

Приведенный ниже запрос является расширенной версией вышеуказанного запроса. Это тоже работает правильно.

select * from 
table 
where ((@value is null) 
    or (@value is not null and column = @value))

Могут ли вышеуказанные 2 запроса воспользоваться преимуществом индекса?

Запрос 2: Приведенный ниже запрос сравнивает столбец с ненулевым @value, иначе сравнивает столбец column с самим собой, который всегда будет истинным, и возвращает все. Это тоже работает правильно. Будет ли этот запрос использовать индекс?

select * from
table
where (column = isnull(@value, column))

Какой самый лучший способ?

Примечание. Если ответ зависит от базы данных, меня интересует MS-SQL.

Ответы [ 2 ]

2 голосов
/ 24 июня 2010

Вариации по этому вопросу возникали несколько раз за последние пару дней (почему это всегда происходит в группах?). Короткий ответ: да, SQL Server будет закорачивать логику, ЕСЛИ создает план запроса с известными значениями. Итак, если у вас есть этот код в сценарии, в котором установлены переменные, то я считаю, что он должен закорачивать логику (проверить, чтобы убедиться). Однако, если он находится в хранимой процедуре, SQL Server заранее создаст план запроса и не будет знать, может ли он замкнуть запрос, потому что он не знает значений параметров во время генерации. план запроса.

Независимо от того, короткое замыкание или нет, SQL Server должен иметь возможность использовать индекс, если это единственная часть вашего запроса. Если переменная имеет значение NULL, то, вероятно, вы не хотите, чтобы SQL Server использовал индекс, потому что он будет бесполезным.

Если вы находитесь в хранимой процедуре, тогда лучше всего использовать OPTION (RECOMPILE) в вашем запросе. Это заставит SQL Server каждый раз создавать новый план запроса. Это немного накладные расходы, но выгоды обычно перевешивают это намного. Это подходит ТОЛЬКО для SQL 2008 и даже только для некоторых более поздних пакетов обновлений. До этого была ошибка с RECOMPILE, которая делала его бесполезным. За дополнительной информацией обращайтесь к замечательной статье Эрланда Соммарскога на эту тему. В частности, вы захотите заглянуть в разделы Статический SQL.

1 голос
/ 24 октября 2013

Чтобы прояснить ситуацию, SQL на самом деле не имеет короткого замыкания, как мы знаем его на языках Си.Короткое замыкание действительно выглядит так, что троичная логика SQL Server в TRUE OR NULL оценивается как TRUE

TRUE OR NULL ===> TRUE
TRUE AND NULL ===> NULL

Например:

if 1=null or 1=1 print 'true' else print 'false'
if 1=null and 1=1 print 'true' else print 'false'
...