Вызов функции в предложении where - PullRequest
7 голосов
/ 12 ноября 2009

У меня есть запрос, как показано ниже:

SELECT * FROM Members (NOLOCK) 
 WHERE Phone= dbo.FormatPhone(@Phone)

Теперь я понимаю, что форматирование должно применяться к переменной в столбце. Но я должен применить его к переменной для присвоения какой-то другой локальной переменной, а затем использовать ее (как показано ниже)

Set @SomeVar = dbo.FormatPhone(@Phone) 

SELECT * 
  FROM Members (NOLOCK) WHERE Phone= @SomeVar

Какой путь лучше или оба хороши?

РЕДАКТИРОВАТЬ: И чем первый запрос отличается от

SELECT * FROM Members (NOLOCK) 
 WHERE dbo.FormatPhone(Phone) = @Phone

Ответы [ 4 ]

8 голосов
/ 12 ноября 2009

Как обычно в SQL, запрос в значительной степени не имеет значения, не зная, против какой фактической схемы используется.

У вас есть индекс на Members.Phone? Если нет, то не имеет значения, как вы пишете запрос, они все будут сканировать всю таблицу и выполнять то же самое (т.е. плохо работать). Если у вас есть индекс , то при написании запроса все будет иметь значение:

SELECT * FROM Members WHERE Phone= @Phone;
SELECT * FROM Members WHERE Phone= dbo.FormatPhone(@Phone);
SELECT * FROM Members WHERE  dbo.FormatPhone(Phone)=@Phone;

Первый запрос гарантированно оптимален, будет искать телефон по индексу.
Второй запрос зависит от характеристик dbo.FormatPhone. Он может использовать или не использовать оптимальный поиск.
Последний запрос гарантированно будет плохим. Буду сканировать таблицу.

Кроме того, я удалил подсказку NOLOCK, похоже, это была тема дня ... См. синтаксис для nolock в sql . NOLOCK всегда неправильный ответ. Использовать изоляцию моментального снимка.

5 голосов
/ 12 ноября 2009

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

4 голосов
/ 12 ноября 2009

Второе, безусловно, предпочтительнее. Первый будет оценивать функцию для каждой строки в таблице, в то время как другой будет выполнять вычисления только один раз.

0 голосов
/ 13 ноября 2009
SELECT * FROM Members (NOLOCK) 
WHERE Phone= dbo.FormatPhone(@Phone)

в приведенном выше запросе function dbo.FormatPhone будет выполняться для каждой строки в таблице Members.

при втором запросе

Set @SomeVar = dbo.FormatPhone(@Phone) 

SELECT * 
FROM Members (NOLOCK) WHERE Phone= @SomeVar

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

...