編輯 - 基於偏好LINQ ORM的,如果可能的話
如果你不需要在ADO中這樣做,更好的解決方案是使用ORM,它將最終構建參數rized ad-hoc sql。這是兩全其美的 - 你可以獲得動態查詢的靈活性,沒有冗餘過濾器來優化優化器,查詢計劃本身是可緩存的,而且你可以安全地避免注入攻擊等問題。和基於的LINQ ORM查詢,可以輕易閱讀:
// 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
回覆,爲什麼WHERE (@x IS NULL OR @x = Column)
一個壞主意?
(從我下面的評論)
雖然「可選參數」模式運作良好的「瑞士軍刀」的小桌子使用時,查詢可選的過濾器的排列的羣衆,不幸的是,大這會導致針對查詢的所有排列的過濾器產生單個查詢計劃,由於parameter sniffing problem的原因,這會導致可選參數的某些排列組的查詢性能較差。如果可能的話,你應該完全消除冗餘過濾器。
回覆:爲什麼應用功能謂詞是一個壞主意
例如
WHERE SomeFunction(Column) = @someParameter
使用的謂詞功能經常不夠格由RDBMS("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