Reputation: 467
This question is almost exactly like mine but none of the answers work with my case.
If it was my question I'd slightly edit it to make it a different question. This question is thus different from the linked one.
Here's the problem: I want a way to match any non-null value ('%'
) AND null values.
The thing is:
I'm using oracle so I can't use IsNull
Some columns are NUMBER
s, which means I can't use COALESCE(column, ' ')
. (ORA-00932: inconsistent datatypes: expected NUMBER got CHAR). However, like '%'
and like '2118'
do work on NUMBER columns.
None of the answers apply to this problem because you can't make a null into an empty string when the column is a NUMBER.
How could I do to achieve this?
Some context:
My procedure takes a lot of parameters, and does a select with all of them. They can all have a value or be null, so if they're null they're replaced with '%'
.
That way, the procedure does :
where t.col1 like param1
and t.col2 like param2
...
Most of the times, only one or two parameters is not null. For the others parameters, the procedure needs to match on every row.
But when the value is null, like '%'
doesn't match the row. I'm looking for a way to match anything when param x is empty (so paramx = '%'
)
Upvotes: 1
Views: 1287
Reputation: 21085
The proposals from other answers based on OR
or NVL
/ COALESCE
are "elegant" and simple, but as a rule they inhibit the index access, which is the most important thing.
You may step down to use dynamic SQL to address the optional parameter problem - which is your case. If a parameter is not passed (it is NULL) - simple ignore it.
So for example with two parameters, if both parameters are passed, generate following SQL
select * from tab t
where t.col1 like :param1
and t.col2 like :param2
If only parameter 1 is given, generate this SQL:
select * from tab t
where t.col1 like :param1
With no parameter you will end with
select * from tab t
Technically it is preferable to have in all SQL statements the same number of bind variables, which is not the case in the above proposal. See this answer for detailed explanation of the trick popularized by Tom Kyte to preserve the number of bind variable with optional parameters.
For example the second statement with only parameter 1 would yield following SQL
select * from tab t
where t.col1 like :param1
and (1=1 or t.col2 like :param2)
The shortcut logik of 1=1
(which is TRUE) eliminates the second part of the predicate, but the bind variable is still used, so the number of the bind variables remains constant.
The big advantage is a fine index range access of this query
Upvotes: 0
Reputation: 191415
My procedure takes a lot of parameters, and does a select with all of them. They can all have a value or be null, so if they're null they're replaced with '%'.
That seems like you're making life hard for yourself. Leave them null, then do:
where (param1 is null or t.col1 like param1)
and (param2 is null or t.col2 like param2)
If param1
(the procedure argument; life is simpler when your parameter/variable names and column names are different... so I've changed the column names to make it a bit clearer) is null it is basically ignored* and all rows pass that part of the filter, whether the column value is null or not null. If param2
is not null then the is null
check for that fails and only rows with (not-null) column values that match param2
value meet that part of the filter.
* Conditions in an or
can be evaluated in any order; putting the is null
check first doesn't necessarily mean the like
won't be evaluated - but the optimiser is pretty smart about that sort of thing
Upvotes: 4
Reputation: 1320
In Oracle NVL can be used instead of ISNULL
IF NVL(aNumberColumn,-1) = -1 THEN
---whatever
END IF;
Upvotes: 1
Reputation: 3016
Oracle automatically converts NUMBER
to VARCHAR2
for like-conditions. So what you have todo is do that yourself so you can use coalesce:
COALESCE(TO_CHAR(column), ' ') like '%'
Upvotes: 0
Reputation: 1270391
If you want to match a specific value and NULL
, you can use OR
:
where col = <specific value> or col is null
Upvotes: 1