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_valuenogensinde 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;