Vous pouvez le faire en utilisant un OR
:
WHERE (@Id > 0 AND Table1.Field = @Id)
OR (@Id = 0 AND Table1.Field IN (6,16,18))
Cependant, je conseillerais d'utiliser (comme vous l'avez dit) IF/ELSE
, lorsque vous mélangez deux conditions comme celle-ci, vous pouvez souvent forcer des plans sous-optimaux. Par exemple, dans votre exemple, vous pouvez simplifier cela en un schéma comme suit :
CREATE TABLE T
( ID INT IDENTITY(1, 1) NOT NULL PRIMARY KEY,
Field INT NOT NULL,
SomeOtherField INT NULL
);
GO
INSERT T (Field)
SELECT Number
FROM Master..spt_values
CROSS JOIN (VALUES (1), (2), (3)) t (A)
WHERE Type = 'P'
GO
CREATE NONCLUSTERED INDEX IX_T_Field ON T (Field) INCLUDE (SomeOtherField);
Cela remplit simplement l'une des colonnes avec les nombres 0-2047 répétés 4 fois chacun (juste pour quelques exemples de données). Alors si je crée deux procédures, une qui utilise 'IF/ELSE' une qui combine les critères comme ci-dessus :
CREATE PROCEDURE dbo.Test @ID INT
AS
SELECT ID, Field, SomeOtherField
FROM T
WHERE (@Id > 0 AND T.Field = @Id)
OR (@Id = 0 AND T.Field IN (6,16,18))
GO
CREATE PROCEDURE dbo.Test2 @ID INT
AS
IF @ID = 0
SELECT ID, Field, SomeOtherField
FROM T
WHERE T.Field IN (6, 16, 18)
ELSE
SELECT ID, Field, SomeOtherField
FROM T
WHERE T.Field = @Id
GO
Étant donné que la compilation des requêtes n'aura lieu qu'une seule fois (sauf si vous indiquez explicitement le contraire), l'optimiseur ne choisira pas un plan différent selon que vous transmettez 0 ou transmettez un ID> 0 à la procédure, donc les deux éléments suivants :
EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;
Donnera ce plan :
La deuxième procédure est capable d'estimer beaucoup mieux le meilleur plan d'exécution, donc exécutez ceci :
EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;
Donne le plan suivant :
Les exemples du monde réel varieront évidemment, et j'ai délibérément construit un exemple qui prouve mon point de vue. Il est légèrement plus difficile de dupliquer beaucoup de code en utilisant IF/ELSE
, mais cela en vaut souvent la peine.