/programming/11329823/add-where-clauses-to-sql-dynamically-programmatically 비슷한 질문에 대한 답변을 볼 수 있습니다
우리는 많은 선택적 매개 변수를 취하고 다음과 같이 필터를 구현하는 SPROC를 발견했습니다.
CREATE PROC MyProc (@optionalParam1 NVARCHAR(50)=NULL, @optionalParam2 INT=NULL)
AS
...
SELECT field1, field2, ... FROM [Table]
WHERE
(@optionalParam1 IS NULL OR MyColumn1 = @optionalParam1)
AND (@optionalParam2 IS NULL OR MyColumn2 = @optionalParam2)
는 실행 된 첫 번째 실행 계획을 캐시 @optionalParam1 = 'Hello World', @optionalParam2 = NULL
하지만 (예 :) 다른 선택적 매개 변수 세트 (예 :)를 전달하면 비참하게 수행됩니다 @optionalParam1 = NULL, @optionalParam2 = 42
. (그리고 분명히 우리는 캐시 된 계획의 성능을 원합니다. WITH RECOMPILE
)
여기서 선택적 매개 변수 외에 매우 선택적이고 적절하게 인덱싱 된 쿼리에 하나 이상의 MANDATORY 필터가있는 경우 위의 PROC가 제대로 수행됩니다.
그러나 모든 필터가 선택 사항 인 경우 매개 변수가있는 동적 SQL은 실제로 성능이 더 우수하다는 것입니다 (선택적 매개 변수의 각 순열에 대해 N! 다른 정적 PROCS를 쓰지 않는 한).
아래의 동적 SQL은 쿼리 매개 변수의 각 순열에 대해 다른 계획을 만들고 캐시하지만 적어도 각 계획은 특정 쿼리에 대해 '맞춤화'됩니다 (PROC인지 Adhoc SQL인지는 중요하지 않음). 매개 변수가있는 쿼리 인 경우 캐시됩니다)
따라서 내 선호도가 :
DECLARE @SQL NVARCHAR(MAX)
-- Mandatory / Static part of the Query here
SET @SQL = N'SELECT * FROM [table] WHERE 1 = 1'
IF @OptionalParam1 IS NOT NULL
BEGIN
SET @SQL = @SQL + N' AND MyColumn1 = @optionalParam1'
END
IF @OptionalParam2 IS NOT NULL
BEGIN
SET @SQL = @SQL + N' AND MyColumn2 = @optionalParam2'
END
EXEC sp_executesql @SQL,
N'@optionalParam1 NVARCHAR(50),
@optionalParam2 INT'
,@optionalParam1 = @optionalParam1
,@optionalParam2 = @optionalParam2
sp_executesql에 중복 매개 변수를 전달해도 상관 없습니다. 무시됩니다. Linq2SQL 및 EF와 같은 ORM은 비슷한 방식으로 매개 변수화 된 동적 SQL을 사용한다는 점에 주목할 가치가 있습니다.