Можете да го направите с помощта на OR
:
WHERE (@Id > 0 AND Table1.Field = @Id)
OR (@Id = 0 AND Table1.Field IN (6,16,18))
Въпреки това бих ви посъветвал да използвате (както казахте) IF/ELSE
, когато комбинирате две условия като това, често можете да наложите неоптимални планове. например във вашия пример можете да опростите това до схема, както следва:
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);
Това просто попълва една от колоните с числата 0-2047, повтарящи се 4 пъти всяко (само за някои примерни данни). След това, ако създам две процедури, една, която използва „IF/ELSE“, друга, която комбинира критериите по-горе:
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
Тъй като компилирането на заявки ще се случи само веднъж (освен ако изрично не кажете друго), оптимизаторът няма да избере различен план в зависимост от това дали подадете 0 или ID> 0 на процедурата, така че и двете от следните:
EXECUTE dbo.Test 0;
EXECUTE dbo.Test 1;
Ще даде този план:
Втората процедура е в състояние да оцени най-добрия план за изпълнение много по-добре, така че стартирайте това:
EXECUTE dbo.Test2 0;
EXECUTE dbo.Test2 1;
Дава следния план:
Примерите от реалния свят очевидно ще варират и аз съзнателно създадох пример, който доказва моята теза. Малко повече усилия е да се дублира много код с помощта на IF/ELSE
, но често си заслужава.