216 votes

SQL : Clause IF dans la clause WHERE

Est-il possible d'utiliser un SI dans une clause dans MS SQL ?

Exemple :

WHERE
    IF IsNumeric(@OrderNumber) = 1
        OrderNumber = @OrderNumber
    ELSE
        OrderNumber LIKE '%' + @OrderNumber + '%'

235voto

bdukes Points 54833

Utilisez un CASE déclaration
UPDATE : La syntaxe précédente (comme indiqué par quelques personnes) ne fonctionne pas. Vous pouvez utiliser CASE comme suit :

WHERE OrderNumber LIKE
  CASE WHEN IsNumeric(@OrderNumber) = 1 THEN 
    @OrderNumber 
  ELSE
    '%' + @OrderNumber
  END

Ou vous pouvez utiliser une instruction IF comme @ N. J. Reed fait remarquer.

0 votes

[Note de l'auteur après l'UPDATE] : Cela devrait fonctionner, mais vous devriez TRIM() des deux côtés pour vous assurer qu'une correspondance est trouvée. J'ai l'impression qu'il y a encore de rares cas limites qui ne correspondent pas.

1 votes

Utilisation de CASE est la solution appropriée dans la plupart des cas. Dans mon cas, je voulais changer l'opérateur de comparaison et j'ai donc utilisé l'approche suivante.

1 votes

Comment pouvons-nous l'utiliser avec l'opérateur IN ?

150voto

njr101 Points 5532

Vous devriez être en mesure de le faire sans aucun IF ou CASE.

 WHERE 
   (IsNumeric(@OrderNumber) AND
      (CAST OrderNumber AS VARCHAR) = (CAST @OrderNumber AS VARCHAR)
 OR
   (NOT IsNumeric(@OrderNumber) AND
       OrderNumber LIKE ('%' + @OrderNumber))

En fonction de la version de SQL, il se peut que vous deviez modifier les casts sur le numéro de commande en INT ou VARCHAR, selon que les casts implicites sont supportés ou non.

Il s'agit d'une technique très courante dans une clause WHERE. Si vous souhaitez appliquer une logique "IF" dans la clause WHERE, il vous suffit d'ajouter la condition supplémentaire avec un AND booléen à la section où elle doit être appliquée.

2 votes

J'imagine que les performances sont un peu moins bonnes qu'avec la solution CASE, puisque toutes ces conditions sont évaluées, non ?

0 votes

J'oublie toujours qu'en SQL on peut remplacer les déclarations conditionnelles par une logique booléenne comme celle-là. Merci pour le rappel, c'est une technique très utile !

1 votes

Cette solution est en fait la meilleure en raison de la façon dont le serveur SQL traite la logique booléenne. Les instructions CASE dans les clauses where sont moins efficaces que les cas booléens car si la première vérification échoue, SQL arrêtera de traiter la ligne et continuera. Cela vous fait gagner du temps de traitement. En outre, placez toujours l'instruction la plus coûteuse de l'autre côté de votre vérification booléenne.

15voto

Euro Micelli Points 12845

Il n'y a pas de bonne façon de faire cela en SQL. Quelques approches que j'ai vues :

1) Utilisez CASE combiné à des opérateurs booléens :

WHERE
    OrderNumber = CASE 
        WHEN (IsNumeric(@OrderNumber) = 1)
        THEN CONVERT(INT, @OrderNumber)
        ELSE -9999 -- Some numeric value that just cannot exist in the column
    END
    OR 
    FirstName LIKE CASE
        WHEN (IsNumeric(@OrderNumber) = 0)
        THEN '%' + @OrderNumber
        ELSE ''
    END

2) Utilisez des IF en dehors du SELECT.

IF (IsNumeric(@OrderNumber)) = 1
BEGIN
    SELECT * FROM Table
    WHERE @OrderNumber = OrderNumber
END ELSE BEGIN
    SELECT * FROM Table
    WHERE OrderNumber LIKE '%' + @OrderNumber
END

3) En utilisant une longue chaîne, composez votre instruction SQL de manière conditionnelle, puis utilisez EXEC

La troisième approche est hideuse, mais c'est presque la seule qui fonctionne si vous avez un certain nombre de conditions variables comme celle-là.

0 votes

La quatrième approche consiste à convertir tous vos IF...ELSE... conditionnels en booléens AND et OR comme dans la réponse de @njr101 ci-dessus. L'inconvénient de cette approche est qu'elle peut s'avérer extrêmement difficile à mettre en œuvre si l'on a de nombreuses IF ou si vous en avez plusieurs qui sont imbriqués.

6voto

Joel Coehoorn Points 190579

Utilisez un CASE au lieu de IF.

4voto

Jeff Martin Points 3958

Vous voulez l'instruction CASE

WHERE OrderNumber LIKE
CASE WHEN IsNumeric(@OrderNumber)=1 THEN @OrderNumber ELSE '%' + @OrderNumber END

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X