2010-11-02 4 views
2

J'ai étudié ce scénario depuis quelques heures maintenant, mais je n'arrive pas à trouver quelque chose qui l'adresse directement.SQL Server 2005 - Clause WHERE - Utiliser IF ou CASE ou BOOLEAN?

J'ai beaucoup de paramètres optionnels passés dans un proc stocké. Je veux renvoyer un jeu d'enregistrements qui est filtré par aucun, un ou plusieurs params facultatifs passés dans le proc stocké. J'essaye de produire une seule requête pour faire ceci.

Voici mon code pseudo (SQL Server 2005):

declare @a varchar(10); set @a = null; 
declare @b varchar(10); set @b = 'comm%'; 

select * from x 
where (if @a is not null then col1 like @a) 
and (if @b is not null then col2 like @b) 

Comme vous pouvez le voir, je veux seulement filtrer col1 si mon param (@a) dispose de données. De même, je veux seulement filtrer sur col2 si mon param (@b) a des données. Si @a et @b sont tous les deux NULL, la requête doit retourner toutes les lignes.

J'ai trouvé plusieurs threads qui se rapprochent de ce que je veux, mais aucun d'entre eux n'emploie la clause LIKE.

Répondre

2
SELECT * FROM X WHERE (@a IS NULL OR col1 LIKE @a) AND (@b IS NULL OR col2 LIKE @b) 
+0

Cela a résolu mon problème. Merci beaucoup :) – Mark

+0

@Mark. Heureux de vous aider! –

4

Vous étiez proche - emploi:

SELECT x.* 
    FROM X x 
WHERE (@a IS NULL OR x.col1 LIKE @a) 
    AND (@b IS NULL OR x.col2 LIKE @b) 

Mais cela est not recommended because it's not sargable. Dynamic SQL serait une meilleure approche:

DECLARE @SQL NVARCHAR(MAX) 
    SET @SQL = N'SELECT x.* 
        FROM X x 
        WHERE 1 = 1 ' 

    SET @SQL = @SQL + CASE 
         WHEN @a IS NULL THEN ' ' 
         ELSE ' AND x.col1 LIKE @a ' 
         END 

    SET @SQL = @SQL + CASE 
         WHEN @b IS NULL THEN ' ' 
         ELSE ' AND x.col2 LIKE @b ' 
         END 

BEGIN 

    EXEC sp_executesql @SQL, 
        N'@a VARCHAR(10), @b VARCHAR(10)', 
        @a, @b 

END 
+0

Certains de mes cols seront indexés, tandis que d'autres ne le seront pas. La flexibilité est plus importante que l'exécution de la requête, donc la sargabilité ne tient pas vraiment compte de mon utilisation. Mais merci pour vos commentaires - je suis sûr que ça va faire la lumière pour les autres sur ce sujet :) – Mark

1

Ce sera probablement la façon la plus efficace de faire ce que vous cherchez. Le filtrage ne se produira que sur une colonne si la valeur transmise à la procédure stockée n'est pas NULL:

CREATE PROCEDURE sproc_example 
@Col1 varchar(30) = NULL, 
@Col2 varchar(30) = NULL, 
@Col3 varchar(30) = NULL 
AS 
SELECT Col1, 
     Col2, 
     Col3 
FROM MyTable 
WHERE Col1 LIKE COALESCE(@Col1,Col1) AND 
     Col2 LIKE COALESCE(@Col2,Col2) AND 
     Col3 LIKE COALESCE(@Col3,Col3) 
+0

Un grand merci pour votre contribution. Votre solution est également idéale et fonctionne pour moi aussi. – Mark

+0

Cette solution n'est appropriée que si vos colonnes n'autorisent pas les valeurs NULL. Sinon, il ne retournera pas les données correctes. –

+0

@G Matros Hmm ... comment ça va? –