1つの方法は、
のバリアントを使用することです。 WHERE column = nvl(var, column)
ただし、ここには2つの落とし穴があります。
-
列がnull許容の場合、この句はnull値をフィルタリングしますが、質問では2番目のケースではnull値をフィルタリングしません。 nullを考慮に入れるようにこの句を変更することはできますが、見苦しくなります:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
もちろん、どういうわけか
impossible_value
挿入されると、他の種類の(楽しい)問題が発生します。 - オプティマイザはこのタイプの句を正しく理解していません。 UNION ALLを使用してプランを作成することもありますが、
nvl
が2つ以上ある場合 、完全に有効なインデックスが存在する場合でも、フルスキャンを取得します。
これが、パラメータがたくさんある場合(たとえば、大きな形式の複数の検索フィールド)、動的SQLを使用するのが好きな理由です。
DECLARE
l_query VARCHAR2(32767) := 'SELECT ... JOIN ... WHERE 1 = 1';
BEGIN
IF param1 IS NOT NULL THEN
l_query := l_query || ' AND column1 = :p1';
ELSE
l_query := l_query || ' AND :p1 IS NULL';
END IF;
/* repeat for each parameter */
...
/* open the cursor dynamically */
OPEN your_ref_cursor FOR l_query USING param1 /*,param2...*/;
END;
EXECUTE IMMEDIATE l_query INTO l_result USING param1;
を使用することもできます。