En metode ville være at bruge en variant af
WHERE column = nvl(var, column)
Der er dog to faldgruber her:
-
hvis kolonnen er nullbar, vil denne klausul filtrere null-værdier, mens du i dit spørgsmål ikke ville filtrere null-værdierne i det andet tilfælde. Du kan ændre denne klausul for at tage nuller i betragtning, men den bliver grim:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Selvfølgelig hvis en eller anden måde
impossible_value
nogensinde er indsat, vil du løbe ind i en anden form for (sjove) problemer. - Optimeringsværktøjet forstår ikke denne type klausul korrekt. Det vil nogle gange producere en plan med en UNION ALL, men hvis der er mere end et par
nvl
, vil du få fuld scanning, selvom der er helt gyldige indekser til stede.
Det er derfor, når der er mange parametre (f.eks. flere søgefelter i stor form), kan jeg godt lide at bruge dynamisk 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;
Du kan også bruge EXECUTE IMMEDIATE l_query INTO l_result USING param1;