Ви можете переглянути відповідь на подібне подібне запитання тут:
/programming/11329823/add-where-clauses-to-sql-dynamically-programmatic
Ми виявили, що 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
це поза)
Виняток тут полягає в тому, що якщо в запиті також є принаймні один ОБОВ'ЯЗКОВИЙ фільтр, який є ВІДВІЛЬНО вибірковим і правильно індексований, крім необов'язкових параметрів, то вищевказаний 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 - вони ігноруються. Варто зазначити, що ORM, як Linq2SQL і EF, використовують параметризований динамічний sql аналогічно.