Es posible que desee ver la respuesta a esta pregunta similar aquí:
/programming/11329823/add-where-clauses-to-sql-dynamically-programmatic
Hemos encontrado que un SPROC que toma un montón de parámetros opcionales e implementa el filtro de esta manera:
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)
almacenará en caché el primer plan de ejecución con el que se ejecuta (p @optionalParam1 = 'Hello World', @optionalParam2 = NULL
. ej. ) pero luego funcionará miserablemente si le pasamos un conjunto diferente de parámetros opcionales (p @optionalParam1 = NULL, @optionalParam2 = 42
. ej .). (Y, obviamente, queremos el rendimiento del plan en caché, por lo que WITH RECOMPILE
está fuera)
La excepción aquí es que si TAMBIÉN hay al menos un filtro OBLIGATORIO en la consulta que es ALTAMENTE selectivo e indexado correctamente, además de los parámetros opcionales, entonces el PROC anterior funcionará bien.
Sin embargo, si TODOS los filtros son opcionales, la verdad bastante horrible es que sql dinámico parametrizado realmente funciona mejor (a menos que escriba N! PROCS estáticos diferentes para cada permutación de parámetros opcionales).
El SQL dinámico como el siguiente creará y almacenará en caché un plan diferente para cada permutación de los parámetros de Consulta, pero al menos cada plan se 'adaptará' a la consulta específica (no importa si es un PROC o Adhoc SQL, como siempre que sean consultas parametrizadas, se almacenarán en caché)
De ahí mi preferencia por:
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
etc. No importa si pasamos parámetros redundantes a sp_executesql, se ignoran. Vale la pena señalar que los ORM como Linq2SQL y EF usan sql dinámico parametrizado de una manera similar.