Du kan gøre det ved at bruge en OR
:
WHERE (@Id > 0 AND Table1.Field = @Id)
OR (@Id = 0 AND Table1.Field IN (6,16,18))
Jeg vil dog anbefale at bruge (som du har sagt) IF/ELSE
, når du mæsker to forhold som denne sammen, kan du ofte fremtvinge suboptimale planer. i dit eksempel kan du forenkle dette til et skema som følger:
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);
Dette udfylder simpelthen en af kolonnerne med tallene 0-2047 gentaget 4 gange hver (bare for nogle eksempler på data). Så hvis jeg opretter to procedurer, en der bruger 'IF/ELSE' en der kombinerer kriterierne som ovenfor:
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
Da kompilering af forespørgsler kun vil ske én gang (medmindre du udtrykkeligt siger andet), vil optimeringsværktøjet ikke vælge en anden plan, afhængigt af om du videregiver 0 eller sender et ID> 0 til proceduren, så begge af følgende:
EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;
Vil give denne plan:
Den anden procedure er i stand til at estimere den bedste udførelsesplan meget bedre, så kør denne:
EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;
Giver følgende plan:
Eksempler fra den virkelige verden vil naturligvis variere, og jeg har bevidst konstrueret et eksempel, der beviser min pointe. Det er lidt mere besvær at duplikere en masse kode ved at bruge IF/ELSE
, men det er ofte det værd.