Salah satu metode adalah dengan menggunakan varian dari
WHERE column = nvl(var, column)
Namun ada dua jebakan di sini:
-
jika kolomnya dapat dibatalkan, klausa ini akan memfilter nilai nol sedangkan dalam pertanyaan Anda, Anda tidak akan memfilter nilai nol dalam kasus kedua. Anda dapat memodifikasi klausa ini untuk mempertimbangkan nol tetapi ternyata jelek:
WHERE nvl(column, impossible_value) = nvl(var, impossible_value)
Tentu saja jika entah bagaimana
impossible_value
pernah dimasukkan, Anda akan mengalami beberapa jenis masalah (menyenangkan). - Pengoptimal tidak memahami dengan benar jenis klausa ini. Kadang-kadang akan menghasilkan rencana dengan UNION ALL tetapi jika ada lebih dari beberapa
nvl
, Anda akan mendapatkan pemindaian penuh meskipun ada indeks yang benar-benar valid.
Inilah sebabnya ketika ada banyak parameter (misalnya beberapa bidang pencarian dalam bentuk besar), saya suka menggunakan SQL dinamis:
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;
Anda juga dapat menggunakan EXECUTE IMMEDIATE l_query INTO l_result USING param1;