2016-05-26 3 views
4

Я ищу мнения и, возможно, конкретный ответ на следующее.
Этот вопрос относится к версии SQL Server 2008 R2 +T-SQL ISNULL, в котором Условие исполнения

В хранимой процедуре, у меня есть дополнительный параметр запроса типа DATE, позволяет называть его @MyVar.

Хранимая процедура выполняет следующий запрос:

SELECT A, B, C 
FROM MyTable 
WHERE MyTable.Field1 = ISNULL(@MyVar,MyTable.Field1) 

Какова стоимость делает ISNULL (@ MYVAR, MyTable.Field1) если @MyVar является NULL? мне интересно, если это лучше разделить случаи, такие как:

IF (@MyVar IS NULL) 
    SELECT A, B, C 
    FROM MyTable 
ELSE 
    SELECT A, B, C 
    FROM MyTable 
    WHERE MyTable.Field1 = @MyVar 

Спасибо!

+2

это предотвратить использование индексов, так как вы сравниваете 'field1' против вычисленного значения каждого поля, которое не может быть индексируются. –

+0

Вы имеете в виду 'WHERE MyTable.Field1 = @ MyVar' в конце. – jarlh

+0

@MarcB Я не понимаю, почему это помешало бы использовать индексы – Lamak

ответ

10

Более изящный подход был бы:

SELECT A, B, C 
FROM MyTable 
WHERE MyTable.Field1 = @MyVar 
    OR @MyVar IS NULL 
OPTION(RECOMPILE) 

редактировать

на основе предложения по @JamesZ, добавил option(recompile) так, что будет использоваться индекс на field1 (если она существует).

edit2 (Спасибо @YB для указания его.)

Если field1 может быть null, а также использовать что-то вроде:

SELECT A, B, C 
    FROM MyTable 
    WHERE MyTable.Field1 = @MyVar 
     OR (@MyVar IS NULL AND MyTable.Field1 IS NULL) 
    OPTION(RECOMPILE) 

Это уже показывает проблемы с 'поймать всех' запросов , Вы также могли бы, например, заменить AND в последнем запросе OR, что дало бы еще один (теоретический) результат, но также потенциально может быть правильным.

+0

Это все еще не использует индексы, но, безусловно, проще читать, хотя я бы добавил круглые скобки, чтобы предотвратить будущие ошибки. –

+0

@JamesZ, если добавлено больше условий, обязательно добавьте круглые скобки. Я не уверен, что вы получаете по поводу индексов. – HoneyBadger

+0

В комментариях об использовании индекса идет обсуждение - и если индексируется поле «Field1», оно не будет использоваться, даже если «@ MyVar» не является нулевым, если не используется опция «option (recompile)». –

0

Для лучшей производительности есть 2 процедуры, одна из которых принимает значение @MyVar, а другая - нет. Таким образом, вы получаете план запроса для каждого случая, а не первый, с которым вы сталкиваетесь (см. parameter sniffing).

Попросите клиента позвонить в зависимости от того, имеет ли смысл использовать или нет.

Если вы обеспокоены дублирования кода добавить view для внутренностей вашего запроса

SELECT A, B, C 
    FROM MyTable 

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

0

Пожалуйста, обратите внимание, что

SELECT A, B, C 
FROM MyTable 
WHERE MyTable.Field1 = ISNULL(@MyVar,MyTable.Field1) 

не возвращать записи, где Field1 is NULL тогда

IF (@MyVar IS NULL) 
    SELECT A, B, C 
    FROM MyTable 
ELSE 
    SELECT A, B, C 
    FROM MyTable 
    WHERE MyTable.Field1 = @MyVar 

бы.

Технически правильный и эффективный способ переписать исходное выражение будет:

SELECT A, B, C 
FROM MyTable 
WHERE @MyVar IS NULL AND MyTable.Field1 IS NOT NULL 
UNION ALL 
SELECT A, B, C 
FROM MyTable 
WHERE @MyVar IS NOT NULL AND MyTable.Field1 = @MyVar 
Смежные вопросы