Избегать ветвления в хранимых процедурах, которые возвращают результаты поиска? - PullRequest
1 голос
/ 22 июня 2010

У меня есть приложение, которое должно возвращать результаты поиска из базы данных SQL Server 2008. Я хотел бы использовать одну хранимую процедуру для возврата результатов, но я обнаружил, что при построении хранимой процедуры она полна многих других. Иначе Если операторы с запросом повторяются снова и снова с небольшими вариациями в зависимости от поиска пользователей критерии.

Есть ли лучший способ сделать это? Я пытаюсь избежать написания динамического SQL, потому что хотел бы получить преимущества от плана выполнения, но я думаю, что должен быть лучший способ. Есть ли у кого-нибудь предложения или, возможно, примеры того, как лучше всего спроектировать хранимую процедуру, которая должна иметь дело со многими параметрами поиска, многие из которых могут быть NULL? Спасибо.

Ответы [ 3 ]

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

Не совсем.

В SQL Server 2005 и более поздних версиях с перекомпиляцией на уровне операторов меньше штрафов с предложениями OR, просто сложность обслуживания.

Использование подхода Ричарда Харрисона ухудшает ситуациюпотому что OR не sargable, работает медленно, скорее всего, не будет использовать индексы.

Динамический SQL открывает проблемы внедрения SQL, цитирования и кэширования.

Это оставляет sp_executesql согласно ответу CountZero,по-прежнему требует создания строк.

Решение может не основываться на коде ... Вам действительно нужен поиск по всем полям одновременно?Я бы попытался разделить на простой и расширенный поиск или выяснить, какие из них наиболее распространены, и попытаться охватить эти запросы.

1 голос
/ 22 июня 2010

Я всегда делал это, используя значения и условия по умолчанию;например,

CREATE PROCEDURE [dbo].[searchForElement]
(
    @Town     nvarchar(100) = '',
    @County   nvarchar(100) = '',
    @postcode nvarchar(100) = ''
)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT <fields> 

    FROM table 
    WHERE 
        (@Town = ''             OR Town     LIKE '%'+@Town+'%')
        AND (@County = ''       OR County   LIKE '%'+@County+'%')
        AND (@postcode = ''     OR postcode LIKE '%'+@PostCode +'%')
END

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

Как правильно @gbn рекомендует, приведенное выше приведет к сканированию индекса, что может быть проблемой для больших таблиц.Если это проблема, решение состоит в том, чтобы ниже использовать ISNULL и тот факт, что добавление NULL к чему-либо приводит к NULL , это позволит искать индекс, потому что% 'понимается оптимизатором (протестировано на SQL2008).Это может быть менее читабельным, но лучше использовать индексы.

CREATE PROCEDURE [dbo].[searchForElement]
(
    @Town     nvarchar(100) = NULL,
    @County   nvarchar(100) = NULL,
    @postcode nvarchar(100) = NULL
)
AS
BEGIN
    SET NOCOUNT ON;

    SELECT <fields> 

    FROM table 
    WHERE   Town     LIKE ISNULL('%'+@Town+'%', '%')
       AND  County   LIKE ISNULL('%'+@County+'%', '%')
       AND  Postcode LIKE ISNULL('%'+@PostCode +'%', '%')
END
0 голосов
/ 22 июня 2010

Я всегда сталкиваюсь с этой проблемой сам.Склонны использовать динамический SQL, если вы используете sp_executesql, то оптимизатор будет пытаться использовать тот же план выполнения.

http://ayyanar.blogspot.com/2007/11/performance-difference-between-exec-and.html

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...