2012-04-17 15 views
23

Supongamos que hay un procedimiento almacenado que tiene 3 params. De todas las posibilidades, estoy buscando para lograr esto con una sola cláusula WHERE sin llegar fuera de control con el uso de () AND() OR() demasiado ...Argumentos opcionales en WHERE Cláusula

Ejemplo:

//Params 
@CITY VARCHAR(100) = NULL, 
@GENDER VARCHAR(100) = NULL, 
@AGE VARCHAR(100) = NULL 

supongo que puede hacerlo usando IF BEGIN ... END para cada variable si existe, pero eso hace que el código sea mucho más largo que el deseado ...

Este método a continuación no funcionará porque es demasiado largo (hay aproximadamente 10 campos diferentes como este, pero el ejemplo es solo 3.) y no estoy seguro de si incluso directamente obtiene valores distintivos ...

SELECT NAME FROM TABLE 
WHERE (
([email protected] AND [email protected] AND [email protected]) 
OR ([email protected] AND [email protected]) 
OR ([email protected] AND [email protected]) 
OR ([email protected] AND [email protected]) 
OR ([email protected]) 
OR ([email protected]) 
OR ([email protected]) 
) 

¿Existe alguna forma más eficiente para hacer esto?

En caso afirmativo, es preferible que el método también sea compatible con JOIN.

+1

Side-nota: cuando se define un VARCHAR() '- como un parámetro para un programa almacenado o una variable local - ¡** siempre ** debe tener ** una duración ** definida! De lo contrario, podría terminar con cadenas 'VARCHAR (1)' inadvertidamente ... –

+0

Campos opcionales que significan si no hay ningún valor o 'NULL', y luego no lo muestran en la cláusula Where, ¿es posible? –

+2

Lea esto: [Condiciones dinámicas de búsqueda en T-SQL] (http://sommarskog.se/dyn-search-2008.html) –

Respuesta

41

Como alternativa a los ISNULL/COALESCE opciones, puede probar los parámetros por ser nulo:

SELECT NAME 
FROM TABLE 
WHERE 
    (@City IS NULL OR City = @City) 
AND 
    (@Gender IS NULL OR Gender = @Gender) 
AND 
    (@Age IS NULL OR Age = @Age) 
+4

Sé que es un poco tarde para hacer un comentario, pero tenga cuidado con este enfoque, ya que SQL Server no garantiza el orden de la evaluación (no hará el cortocircuito). Por lo tanto, podría terminar SQL Server haciendo todas las comprobaciones innecesarias. –

+1

@IlyaChernomordik: Y el rendimiento de descarga cuesta abajo. – Neolisk

+0

@IlyaChernomordik, entonces, ¿cuál sería una mejor manera de hacer esto? Se piensa en sql dinámico pero trae otros problemas como mantenimiento, eliminación de código, etc. ¿No hay otra manera mejor? –

0

Posiblemente esto:

create procedure myProc 
    --Params 
@CITY VARCHAR(100) = NULL, 
@GENDER VARCHAR(100) = NULL, 
@AGE VARCHAR(100) = NULL 
as 

SELECT NAME FROM [TABLE] 
WHERE ISNULL(CITY,'')=ISNULL(@CITY,ISNULL(CITY,'')) 
AND ISNULL(GENDER,'')=ISNULL(@GENDER,ISNULL(GENDER,'')) 
AND ISNULL(AGE,'')=ISNULL(@AGE,ISNULL(AGE,'')) 
go 

Suponiendo que las columnas en la cláusula WHERE es anulable, utilizando ISNULL para evitar la comparación nula.

+0

uggghhh .. quería evitar hacerlo de esa manera ... ¿algo así como 'IsNull'? –

+0

Puede probar esta opción –

4

intentar algo como esto:

SELECT NAME 
FROM TABLE 
WHERE 
    City = IsNull(@City, City) AND 
    Gender = IsNull(@Gender, Gender) AND 
    Age = IsNull(@Age, Age) 

O:

SELECT NAME 
FROM TABLE 
WHERE 
    (City = @City OR @City IS NULL) AND 
    (Gender = @Gender OR @Gender IS NULL) AND 
    (Age = @Age OR @Age IS NULL) 
+0

Creo que su primer ejemplo puede cortarlo, déjame verlo ... brb. –

+0

Con respecto a la primera opción ... ¿NULL es igual a NULL? –

+0

'Seleccionar * De la tabla Donde NULL IS NULL' devolverá todas las filas. Eso está bien en este contexto porque significa que no desea filtrar por el argumento si le pasa un valor 'NULL'. – Greg

10

qué pasa con esto?

SELECT 
    NAME 
FROM TABLE 
WHERE CITY = COALESCE(@CITY, CITY) 
    AND GENDER = COALESCE(@GENDER, GENDER) 
    AND AGE = COALESCE(@AGE, AGE) 
+1

¡Hermoso! Con suerte, SQL Server puede optimizar las condiciones si se encuentran variables nulas. Sería interesante probarlo – l33t

1
SELECT NAME 
FROM TABLE 
WHERE  
    City = case when isnull(@City ,'') = '' then City 
         else @City end 
AND  
    Gender = case when isnull(@Gender ,'') = '' then Gender 
         else @Gender end 
AND 
    Age = case when isnull(@Age ,0) = 0 then Age 
         else @Age end  
+0

Dudo que la condición City = City y en general Column = Column Condition sea una condición ineficaz, por ejemplo null = null podría llevarnos a UNKNOWN y, por otro lado, si nuestra columna sería no nula, terminamos con una tabla de exploración completa para la columna = condición de columna. – siamak