Я создаю хранимую процедуру для поиска в таблице. У меня есть много разных полей поиска, все из которых являются необязательными. Есть ли способ создать хранимую процедуру, которая будет обрабатывать это? Допустим, у меня есть таблица с четырьмя полями: ID, FirstName, LastName и Title. Я мог бы сделать что-то вроде этого:
CREATE PROCEDURE spDoSearch
@FirstName varchar(25) = null,
@LastName varchar(25) = null,
@Title varchar(25) = null
AS
BEGIN
SELECT ID, FirstName, LastName, Title
FROM tblUsers
WHERE
FirstName = ISNULL(@FirstName, FirstName) AND
LastName = ISNULL(@LastName, LastName) AND
Title = ISNULL(@Title, Title)
END
Такого рода работы. Однако он игнорирует записи, в которых FirstName, LastName или Title имеют значение NULL. Если заголовок не указан в параметрах поиска, я хочу включить записи, где заголовок равен NULL - то же самое для FirstName и LastName. Я знаю, что мог бы сделать это с помощью динамического SQL, но я бы хотел этого избежать.
tsql
optional-parameters
Кори Бернетт
источник
источник
code
выполнить инструкцию where : ISNULL (FirstName, ') = ISNULL (@FirstName,' ') - это сделает каждый NULL пустой строкой, и их можно сравнить через eq. оператор. Если вы хотите получить все заголовки, если входной параметр равен нулю, попробуйте что-то вроде этого:code
FirstName = @FirstName ИЛИ @FirstName IS NULL.Ответы:
Динамическое изменение поисков на основе заданных параметров - сложная задача, и выполнение одного способа по другому, даже с очень небольшим отличием, может иметь серьезные последствия для производительности. Ключ заключается в том, чтобы использовать индекс, игнорировать компактный код, игнорировать беспокойство по поводу повторения кода, вы должны составить хороший план выполнения запроса (используйте индекс).
Прочитайте это и рассмотрите все методы. Ваш лучший метод будет зависеть от ваших параметров, ваших данных, вашей схемы и вашего фактического использования:
Условия динамического поиска в T-SQL by Эрланд Соммарског
Проклятие и благословения динамического SQL Эрланда Соммарского
Если у вас есть правильная версия SQL Server 2008 (SQL 2008 с пакетом обновления 1 (SP1) CU5 (10.0.2746) и выше), вы можете использовать этот маленький трюк для фактического использования индекса:
Добавьте
OPTION (RECOMPILE)
к вашему запросу, см. Статью Эрланда , и SQL Server разрешит егоOR
изнутри(@LastName IS NULL OR LastName= @LastName)
до того, как план запроса будет создан на основе значений времени выполнения локальных переменных, и индекс может быть использован.Это будет работать для любой версии SQL Server (возвращать правильные результаты), но включайте только OPTION (RECOMPILE), если вы используете SQL 2008 SP1 CU5 (10.0.2746) и выше. ОПЦИЯ (RECOMPILE) перекомпилирует ваш запрос, только перечисленная версия перекомпилирует его на основе текущих значений времени выполнения локальных переменных, что даст вам наилучшую производительность. Если не в этой версии SQL Server 2008, просто оставьте эту строку отключенной.
источник
Ответ @KM хорош, но он не в состоянии полностью выполнить один из его ранних советов;
Если вы хотите добиться максимальной производительности, вам следует написать индивидуальный запрос для каждой возможной комбинации необязательных критериев. Это может показаться экстремальным, и если у вас есть много дополнительных критериев, то это может быть, но производительность часто является компромиссом между усилием и результатами. На практике может существовать общий набор комбинаций параметров, которые могут быть нацелены на заказные запросы, затем общий запрос (согласно другим ответам) для всех других комбинаций.
Преимущество этого подхода состоит в том, что в общих случаях, обрабатываемых заказными запросами, запрос настолько эффективен, насколько это возможно - это не влияет на непредоставленные критерии. Кроме того, индексы и другие улучшения производительности могут быть нацелены на конкретные заказные запросы, а не пытаться удовлетворить все возможные ситуации.
источник
Вы можете сделать в следующем случае,
Однако в зависимости от данных иногда лучше создавать динамические запросы и выполнять их.
источник
Пять лет опоздал на вечеринку.
Это упомянуто в предоставленных ссылках принятого ответа, но я думаю, что оно заслуживает явного ответа на SO - динамическое построение запроса на основе предоставленных параметров. Например:
Настроить
Процедура
использование
Плюсы:
Минусы:
Не прямой ответ, но связанный с проблемой, иначе общая картина
Обычно эти фильтрующие хранимые процедуры не распространяются, а вызываются из некоторого сервисного уровня. Это оставляет возможность перенести бизнес-логику (фильтрацию) с SQL на уровень обслуживания.
Одним из примеров является использование LINQ2SQL для генерации запроса на основе предоставленных фильтров:
Плюсы:
Минусы:
источник
Продлите ваше
WHERE
состояние:т.е. объединить разные случаи с логическими условиями.
источник
Это также работает:
источник