web-dev-qa-db-fra.com

OÙ IS NUL, IS Clause NOT NULL ou NO WHERE selon la valeur du paramètre SQL Server

J'ai une procédure stockée dans SQL Server 2000 qui effectue une recherche basée sur les valeurs de paramètre. Pour l’un des paramètres passés, il me faut une clause WHERE différente en fonction de sa valeur - le problème est que les 3 valeurs seraient où MyColumn 

  1. IS NULL 
  2. IS NOT NULL
  3. ANY VALUE (NULL AND NOT NULL) (essentiellement pas de clause WHERE)

J'ai un problème mental à trouver la bonne syntaxe. Est-ce possible de le faire en une seule instruction select sans effectuer une branche IF @parameter BEGIN ... END?

30
Russ Cam

Voici comment résoudre ce problème à l'aide d'une seule clause WHERE:

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

Un usage naïf de l'instruction CASE ne fonctionne pas, j'entends par ceci:

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

Il est possible de résoudre ce problème en utilisant une déclaration de cas, voir onedaywhen's answer

39

Vous pouvez juste faire quelque chose comme ça:

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

Quelque chose comme ca.

13
BobbyShaftoe

Voici comment cela peut être fait en utilisant 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;
10
onedaywhen
WHERE MyColumn = COALESCE(@value,MyColumn) 
  • Si @value est NULL, il comparera MyColumn à lui-même, en ignorant la clause @value = no where.

  • SI @value a une valeur (NOT NULL), il comparera MyColumn à @value.

Référence:COALESCE (Transact-SQL) .

10
Chad Grant

Une autre façon de CASE:

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
5
Croton

J'ai eu du succès avec cette solution. C'est presque comme chez Patrick, avec une petite tournure. Vous pouvez utiliser ces expressions séparément ou en séquence. Si le paramètre est vide, il sera ignoré et toutes les valeurs de la colonne que vous recherchez seront affichées, y compris 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 = '')
0
Marc D