Du kan jämföra kolumnen och värdet för att se om båda är null; eller båda är inte-null och lika:
SELECT * FROM MYTABLE
WHERE ((A is null and :1 is null) or A = :1)
AND ((B is null and :2 is null) or B = :2)
AND ((C is null and :3 is null) or C = :3)
AND ((D is null and :4 is null) or D = :4)
AND ((E is null and :5 is null) or E = :5)
Vilket inte är särskilt vackert men borde fungera. Som du redan vet kan du inte jämföra värden mot null med likhet, bara is
operatör.
Beroende på din klientprogramvara kanske du kan använda namngivna bindningsvariabler för att undvika att behöva upprepa bindningarna; om inte kan du använda en underfråga eller CTE som tar bindningarna och sedan använda dem i huvudfrågan. Något i stil med:
WITH CTE AS (
SELECT :1 AS val_1, :2 AS val_2, :3 AS val_3, :4 AS val_4, :5 AS val_5
FROM DUAL
)
SELECT MT.*
FROM CTE
JOIN MYTABLE MT
ON ((MT.A is null and CTE.val_1 is null) or MT.A = CTE.val_1)
AND ((MT.B is null and CTE.val_2 is null) or MT.B = CTE.val_2)
AND ((MT.C is null and CTE.val_3 is null) or MT.C = CTE.val_3)
AND ((MT.D is null and CTE.val_4 is null) or MT.D = CTE.val_4)
AND ((MT.E is null and CTE.val_5 is null) or MT.E = CTE.val_5)
Gordons funktionsbaserade indexmetod kan vara mer tillförlitlig och lättare att förstå, så länge du verkligen aldrig kan ha några kolumner med det magiska värdet noll. (Jag hade missat den raden i din fråga också och hade inte insett att du redan hade räknat bort det!)