ほぼ間違いなく、2 つの選択で IF ステートメントを使用する必要があります。例えば
IF @Name IS NULL
BEGIN
SELECT *
FROM Person
END
ELSE
BEGIN
SELECT *
FROM Person
--WHERE Name LIKE '%' + @Name + '%'
WHERE Name = @Name
END
注意LIKE
: ワイルドカードがなくても equals , と変わらないため、 like を equals に変更しました。パフォーマンスの点では何の違いもありませんが、クエリを読む次の人にとってあいまいさがなくなります。正確でない一致が必要な場合は、コメントアウトされたものを使用し、WHERE
必要に応じてワイルドカードを削除してください。
その理由はIF
、2 つのクエリの実行計画が大きく異なる可能性があるためです。ただし、それらを 1 つのクエリに結合することで、オプティマイザにいずれかの計画を選択させることになります。次のスキーマを想像してください。
CREATE TABLE Person
( PersonID INT IDENTITY(1, 1) NOT NULL,
Name VARCHAR(255) NOT NULL,
DateOfBirth DATE NULL
CONSTRAINT PK_Person_PersonID PRIMARY KEY (PersonID)
);
GO
CREATE NONCLUSTERED INDEX IX_Person_Name ON Person (Name) INCLUDE (DateOfBirth);
GO
INSERT Person (Name)
SELECT DISTINCT LEFT(Name, 50)
FROM sys.all_objects;
GO
CREATE PROCEDURE GetPeopleByName1 @Name VARCHAR(50)
AS
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE Name IN (SELECT Name FROM Person WHERE Name LIKE ISNULL(@Name, Name));
GO
CREATE PROCEDURE GetPeopleByName2 @Name VARCHAR(50)
AS
IF @Name IS NULL
SELECT PersonID, Name, DateOfBirth
FROM Person
ELSE
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE Name = @Name;
GO
ここで、値がある場合とない場合の両方の手順を実行すると、次のようになります。
EXECUTE GetPeopleByName1 'asymmetric_keys';
EXECUTE GetPeopleByName1 NULL;
EXECUTE GetPeopleByName2 'asymmetric_keys';
EXECUTE GetPeopleByName2 NULL;
結果は両方の手順で同じですが、最初の手順では毎回同じ計画が得られますが、2 番目の手順では 2 つの異なる計画が得られます。どちらも最初の手順よりもはるかに効率的です。

を使用できない場合IF
(たとえば、インライン テーブル値関数を使用している場合) は、以下を使用して同様の結果を得ることができますUNION ALL
。
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE @Name IS NULL
UNION ALL
SELECT PersonID, Name, DateOfBirth
FROM Person
WHERE Name = @Name;
これは IF を使用するほど効率的ではありませんが、最初のクエリよりも効率的です。要するに、少ないほど常に多いとは限らないということです。はい、usingIF
はより冗長であり、より多くの作業を行っているように見えるかもしれませんが、実際にははるかに少ない作業を行っており、はるかに効率的です。