Jednou z metod by bylo použití varianty
WHERE column = nvl(var, column)
Jsou zde však dvě úskalí:
-
pokud má sloupec hodnotu null, bude tato klauzule filtrovat hodnoty null, zatímco ve vaší otázce byste v druhém případě nefiltrovali hodnoty null. Tuto klauzuli byste mohli upravit tak, aby zohledňovala nuly, ale je to ošklivé:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Samozřejmě pokud nějak
impossible_value
je někdy vložen, narazíte na nějaký jiný druh (zábavných) problémů. - Optimalizátor tomuto typu klauzule správně nerozumí. Někdy vytvoří plán s UNION ALL, ale pokud existuje více než pár
nvl
, získáte úplnou kontrolu, i když jsou přítomny dokonale platné indexy.
To je důvod, proč, když existuje mnoho parametrů (například několik vyhledávacích polí ve velké formě), rád používám dynamické 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;
Můžete také použít EXECUTE IMMEDIATE l_query INTO l_result USING param1;