Je kunt het doen met een OR
:
WHERE (@Id > 0 AND Table1.Field = @Id)
OR (@Id = 0 AND Table1.Field IN (6,16,18))
Ik zou echter adviseren om (zoals je hebt gezegd) IF/ELSE
. te gebruiken , als je twee voorwaarden zoals deze combineert, kun je vaak suboptimale plannen forceren. In uw voorbeeld kunt u dit bijvoorbeeld als volgt vereenvoudigen tot een schema:
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);
Dit vult eenvoudig een van de kolommen met de nummers 0-2047 die elk 4 keer worden herhaald (alleen voor enkele voorbeeldgegevens). Dan Als ik twee procedures maak, een die 'IF/ELSE' gebruikt en een die de bovenstaande criteria combineert:
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
Aangezien het compileren van query's slechts één keer plaatsvindt (tenzij u expliciet anders zegt), zal de optimizer geen ander plan kiezen, afhankelijk van of u 0 doorgeeft of een ID> 0 doorgeeft aan de procedure, dus beide:
EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;
Zal dit plan geven:
De tweede procedure kan het beste uitvoeringsplan veel beter inschatten, dus voer dit uit:
EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;
Geeft het volgende plan:
Voorbeelden uit de echte wereld zullen uiteraard variëren, en ik heb bewust een voorbeeld gemaakt dat mijn punt bewijst. Het kost iets meer moeite om veel code te dupliceren met IF/ELSE
, maar het is vaak de moeite waard.