2012-02-21 3 views
2

У меня возникла ситуация, когда я вызываю хранимую процедуру и передаю некоторые переменные. В некоторых случаях я буду передавать значение null, и я хочу, чтобы он возвращал все. Возьмите следующее (возраст - целая колонка):T-SQL Где int = @ var/@ var = null?

[Table] 
[Name] | [Age] 
Mike | 22 
Fred | 18 
Bob | 22 



SELECT * FROM [table] WHERE [Age][email protected] 

Теперь, если я перейду в 22, я получу Майка и Боба. Точно так же, пройдя в 18, я получу Фред. Однако, что, если я хочу, чтобы все 3 строки, когда я проходил в null/не устанавливали @AgeVar? Это моя проблема в очень простом масштабе.

Редактировать: Sproc довольно сложный, и я действительно не хочу удвоить все разделы, имея необходимость, но их дважды, как в одном из ответов ниже. Есть ли другие методы?

+5

Читать [Catch-all queries] (http://sqlinthewild.co.za/index.php/2009/03/19/catch-all-queries/) –

+2

Если у вас нет времени, чтобы нажать на Joe's ссылка на его замечательную статью, он демонстрирует, что использование динамического SQL может очень хорошо превзойти этот подход. – DOK

+1

@ DOK: Чтобы быть ясным, я не автор статьи. Эта статья была написана Гейлом Шоу, который намного умнее, чем я рассматриваю SQL Server. –

ответ

9
SELECT * FROM [table] WHERE [Age][email protected] OR @AgeVar IS NULL 

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

+0

Это блестящий ответ. никогда не думал об этом так. Brilliant. Я запомню это как ответ через некоторое время, так как он говорит, что я к чему. Но спасибо!! – Piercy

+8

JUST FYI ... это хаос с планами выполнения запросов в SqlServer ... нам недавно пришлось реорганизовать кучу SPROC из-за запросов, подобных выше. –

+1

@EoinCampbell: Это точка в блоге, которую я привел в своем комментарии к вопросу. –

3
IF @AgeVar IS NULL 
    BEGIN 
     SELECT * 
     FROM @Table 
    END 
ELSE 
    BEGIN 
     SELECT * 
     FROM @Table 
     WHERE Age = @AgeVar 
    END 
+0

Да, я рассматривал что-то вроде этого, но Хранилище Процедура, в которой я делаю это, довольно огромная и не хочет сегментировать каждый раздел на две части только для этого. Есть ли другой способ? – Piercy

+0

Опция 'OR', уже опубликованная, будет работать, как' WHERE \t ISNULL (@ AgeVar, [Age]) = [Age] '. Однако вышеописанный вариант лучше оптимизирован оптимизатором. Вы можете подумать о создании временной таблицы, заполнив ее с помощью' IF ...ELSE ", а затем ссылаясь на это позже в процедуре, но это может ухудшиться в зависимости от остальной части процедуры и указаний и т. Д. – GarethD

+0

Я был бы обеспокоен кэшированием плана запроса с этим. –

1

Я обнаружил, что если у вас есть общий случай, используйте инструкцию CASE. Это приведет к перетаскиванию производительности только в редком случае. Итак, если вы чаще передаете значение null в качестве параметра, то это будет более эффективным.

SELECT * 
FROM [table] 
WHERE 
    0 = 
     CASE 
      WHEN @AgeVar IS NULL THEN 0 
      WHEN [Age][email protected] THEN 0 
     END 
+0

Я действительно не проверял это, но мне кажется, что это не сработает: если [Возраст] = @AgeVar, тогда окончательный запрос будет выглядеть как выберите * из [таблицы] где 0 = 0 ... и вы получите ВСЕ записи! –

+0

Я использовал это для большого успеха во многих случаях. Подумайте о том, как работает SQL, и это должно иметь смысл. Он похож на существо. Выбор * из [таблицы], где 0 = 0, встречается только в случае, когда столбец [Возраст] текущей строки равен @AgeVar. По вашей логике, когда любое совпадение в SQL делается вообще, тогда все записи будут возвращаться –

1

Это даст вам гораздо лучшую производительность, чем метод [Age][email protected] OR @AgeVar IS NULL, потому что он будет генерировать индекс стремится вместо сканирования индекса:

SELECT * FROM [Table1] 
WHERE COALESCE(@AgeVar, Age) = Age 

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