2009-05-01 9 views
27

Tengo un procedimiento almacenado en SQL Server 2000 que realiza una búsqueda basada en los valores de los parámetros. Para uno de los parámetros pasados ​​en, necesito una cláusula diferente WHERE dependiendo de su valor - el problema es que los 3 valores serían donde MyColumnDONDE ESTÁ NULA, NO ES NULA o NO WHERE cláusula según el valor del parámetro SQL Server

  1. IS NULL
  2. IS NOT NULL
  3. ANY VALUE (NULL AND NOT NULL) (esencialmente no WHERE cláusula)

Estoy teniendo un bloqueo mental para encontrar la sintaxis correcta. ¿Es posible hacerlo en una declaración seleccionada sin realizar alguna ramificación IF @parameter BEGIN ... END?

Respuesta

38

Aquí es cómo se puede solucionar esto usando una sola WHERE cláusula:

WHERE (@myParm = value1 AND MyColumn IS NULL) 
OR (@myParm = value2 AND MyColumn IS NOT NULL) 
OR (@myParm = value3) 

Un uso ingenuo de la instrucción CASE no funciona, con esto quiero decir lo siguiente:

SELECT Field1, Field2 FROM MyTable 
WHERE CASE @myParam 
    WHEN value1 THEN MyColumn IS NULL 
    WHEN value2 THEN MyColumn IS NOT NULL 
    WHEN value3 THEN TRUE 
END 

Es posible resolver esto usando una declaración de caso, vea onedaywhen's answer

+0

Tuviste la misma idea que yo. Sin embargo, necesitas los paréntesis. – BobbyShaftoe

+0

Gracias Bobby, actualicé mi respuesta –

+1

No estoy seguro de si necesita o no * los paréntesis, pero soy un gran defensor de paréntesis en expresiones booleanas complejas. No tenerlos le deja al compilador hacer un orden de operaciones y es bastante aterrador, si me preguntas. –

-1

Debe Eche un vistazo a la declaración CASE.

+0

Sí, este es otro buen método. – BobbyShaftoe

+0

No creo que pueda usar la instrucción CASE en este escenario ya que CASE evalúa una expresión de resultado –

+0

No es tan sencillo como pensé que era en este caso. Podría agregar una declaración de caso a su cláusula de selección que haga lo mismo que la cláusula WHERE OR-together junto, pero eso solo le daría una declaración SQL menos legible. Actualicé mi respuesta para mostrar esto. –

12

Se podía hacer algo como esto:

SELECT * 
FROM foo 
WHERE (@param = 0 AND MyColumn IS NULL) 
OR (@param = 1 AND MyColumn IS NOT NULL) 
OR (@param = 2) 

Algo por el estilo.

+0

Digamos que necesito filtrar por una cadena. Si la cadena es nula debería devolver todos los registros de una tabla, si no es nula debería devolver todos los registros que coinciden con la cadena o parte de ella (operador LIKE). ¿Cómo resolverías eso? – Axel

9
WHERE MyColumn = COALESCE(@value,MyColumn) 
  • Si es @valueNULL, comparará MyColumn a sí mismo, haciendo caso omiso de @value = no where cláusula.

  • SI @value tiene un valor (NOT NULL) se comparará MyColumn a @value.

Referencia:COALESCE (Transact-SQL).

+0

No creo que pueda usar la instrucción CASE en este escenario ya que CASE evalúa una expresión de resultado. COALESCE o incluso ISNULL. No creo que tampoco funcionará. –

+0

por favor revise mi edición, ¿me falta algo por completo en su pregunta? –

+0

@Deviant - Creo que te falta un poco la pregunta. La cláusula WHERE en MyColumn necesita establecerse en otro valor porque no se relaciona directamente con el valor del parámetro, es decir, si se pasa NULL, entonces se niega la cláusula WHERE. Si se pasa cualquier otro valor, entonces el conjunto de resultados será solo para WHERE MyColumn es igual a ese valor, no MyColumn tiene un valor conocido. La cláusula WHERE de MyColumn que tiene un valor NULL no se trata. –

10

Ésta es la forma en que se puede hacer utilizando CASE:

DECLARE @myParam INT; 
SET @myParam = 1; 

SELECT * 
    FROM MyTable 
WHERE 'T' = CASE @myParam 
      WHEN 1 THEN 
       CASE WHEN MyColumn IS NULL THEN 'T' END 
      WHEN 2 THEN 
       CASE WHEN MyColumn IS NOT NULL THEN 'T' END 
      WHEN 3 THEN 'T' END; 
5

Otra manera de CASO:

SELECT * 
FROM MyTable 
WHERE 1 = CASE WHEN @myParm = value1 AND MyColumn IS NULL  THEN 1 
       WHEN @myParm = value2 AND MyColumn IS NOT NULL THEN 1 
       WHEN @myParm = value3       THEN 1 
      END 
+0

+1 solución interesstion. :) –

0

que he tenido éxito con esta solución. Es casi como el de Patrick, con un pequeño giro. Puede usar estas expresiones por separado o en secuencia. Si el parámetro está en blanco, se ignorará y se mostrarán todos los valores de la columna que buscará, incluyendo NULLS.

SELECT * FROM MyTable 
WHERE 
    --check to see if @param1 exists, if @param1 is blank, return all 
    --records excluding filters below 
(Col1 LIKE '%' + @param1 + '%' OR @param1 = '') 
AND 
    --where you want to search multiple columns using the same parameter 
    --enclose the first 'OR' expression in braces and enclose the entire 
    --expression 
((Col2 LIKE '%' + @searchString + '%' OR Col3 LIKE '%' + @searchString + '%') OR @searchString = '') 
AND 
    --if your search requires a date you could do the following 
(Cast(DateCol AS DATE) BETWEEN CAST(@dateParam AS Date) AND CAST(GETDATE() AS DATE) OR @dateParam = '') 
Cuestiones relacionadas