Edit - Preference для LINQ на основе ORM, если возможно
Если вам не нужно это делать в ADO, лучшим решением является использование ORM, который в конечном итоге будет создавать параметр red ad-hoc sql. Это лучшее из обоих миров - вы получаете гибкость динамического запроса, без избыточных фильтров, чтобы расстроить оптимизатор, сам план запроса можно кэшировать, и вы можете быть в безопасности от настиг, таких как инъекции. И ORM запрос Linq на основе делает для легкого чтения:
// Build up a non-materialized IQueryable<>
var usersQuery = db.Users;
if (!string.IsNullOrEmpty(userID))
{
usersQuery = usersQuery.Where(u => u.Name == userId);
}
// Of course, you wouldn't dream of storing passwords in cleartext.
if (!string.IsNullOrEmpty(anotherField))
{
usersQuery = usersQuery.Where(u => u.AnotherColumn == anotherField);
}
...
// Materialize (and execute) the query
var filteredUsers = usersQuery.ToList();
Для сложных запросов, вы можете захотеть взглянуть на PredicateBuilder
ADO здания/ручной запроса
Вы можете использовать sp_executesql
для динамически наращивать SQL, как показано ниже. При условии, что вы параметризуете переменные, которые должны быть в безопасности от таких проблем, как SQL-инъекция и экранирование кавычек и т. Д., Будут обработаны для вас.
CREATE PROCEDURE [dbo].[PROC001]
@userID varchar(20),
@password varchar(20),
@optionalParam1 NVARCHAR(50) = NULL -- Other optional parameters
AS
BEGIN
SET NOCOUNT ON
DECLARE @SQL NVARCHAR(MAX)
-- Mandatory/Static part of the Query here.
-- Cleartext passwords are verboten, and RTRIM is redundant in filters
SET @SQL = N'SELECT * FROM tUsers WHERE Name = @userID AND PwdHash = @pwdHash'
IF @OptionalParam1 IS NOT NULL
BEGIN
SET @SQL = @SQL + N' AND AnotherField = @OptionalParam1'
END
EXEC sp_executesql @SQL,
N'@userID varchar(20),
@pwdHash varchar(20),
@optionalParam1 NVARCHAR(50)'
,@userID = @userID
,@pwdHash = @pwdHash
,@optionalParam1 = @optionalParam1
END
Re, почему WHERE (@x IS NULL OR @x = Column)
плохая идея?
(От мой комментарий ниже)
Хотя «необязательный параметр» модель хорошо работает как «швейцарский армейский нож» для запрашивая множество перестановок дополнительных фильтров при использовании на небольших таблицах, к сожалению, большой таблицы, это приводит к единому плану запроса для всех перестановок фильтров для запроса, что может привести к низкой производительности запросов с некоторыми перестановками необязательных параметров из-за parameter sniffing problem. Если возможно, вы должны полностью исключить избыточные фильтры.
Re: Почему применение функций в предикатах плохая идея
например
WHERE SomeFunction(Column) = @someParameter
Использование функций в предикатах часто лишает использование индексов по РСУБД ("non-sargable").
В этом случае RTRIM
не нужен, поскольку сервер Sql ignores завершающие пробелы during comparison.
Возможный дубликат: http://stackoverflow.com/questions/977021/can-a-stored-procedure-have-dynamic-parameters-to-be-used-in-an-in-clause – phadaphunk