6

suppose I have a oracle query

SELECT *
FROM EMPLOYEE
WHERE DEPARTMENT = ?
    AND DESIGNATION = ?
    AND DISTRICT = ?
    AND CIRCLE = ?

And quite possible any 1 or 2 or 3 of the parameter (?) can be empty or null.
so what should I do so that the empty parameters are totally "ignore" in the where clause and only search for the non-empty parameter in the table.
How can I achieve this

Please help.. The query must be compatible oracle 10g. Thanks

10
  • you can build up a query template depending on the paramenter value you have Commented Aug 25, 2017 at 12:44
  • 1
    Something like where (c1 = :param or :param is null) and (c2 = .... Commented Aug 25, 2017 at 12:45
  • Inplace of AND use OR so that either of the conditions are matched. Commented Aug 25, 2017 at 12:45
  • 2
    @XING - Seriously? you think AND and OR can be used interchangeably? Commented Aug 25, 2017 at 12:49
  • Possible duplicate of How to ignore null parameter in a Stored Procedure Oracle Commented Aug 25, 2017 at 12:50

6 Answers 6

11

You can rewrite query like:

select * 
  from EMPLOYEE 
  where (DEPARTMENT  = p1 or p1 is null)  
    and (DESIGNATION = p2 or p2 is null) 
    and (DISTRICT    = p3 or p3 is null)
    and (CIRCLE      = p4 or p4 is null)

or:

select * 
  from EMPLOYEE 
  where DEPARTMENT  = nvl(p1, department)
    and DESIGNATION = nvl(p2, designation)
    and DISTRICT    = nvl(p3, district)
    and CIRCLE      = nvl(p4, circle)

As @mathguy mentioned in comments second version will not show null values. Please use first version.

Sign up to request clarification or add additional context in comments.

7 Comments

Will the second query be able to use column indexes or would the use of a function cause full table scans?
What will the second version do if CIRCLE (say) is NULL in the base table? Is that the desired behavior? The correct answer is the first version you proposed.
@MT0 - why only the second query? You may ask the same question about the first one too. The answer is the same.
I made short test and index was used in nvl version.
@MT0 - My point was that "x = :param or :param is null" also prevents the use of an index. The first version is better than the second, but "ability to use an index" is not among the reasons.
|
1

NVL will be your friend here.

This function takes two input parameters and returns either the first one, or the second one if the first one is NULL.

This would work :

SELECT *
FROM EMPLOYEE
WHERE DEPARTMENT = NVL(yourParam1,DEPARTMENT)
    AND DESIGNATION = NVL(yourParam2,DESIGNATION )
    AND DISTRICT = NVL(yourParam3,DISTRICT )
    AND CIRCLE = NVL(yourParam4,CIRCLE )

4 Comments

@UsagiMiyamoto - Why?
@mathguy NVL evaluates both side, coalesce will do until a value is found. Basically, over large datasets an NVL will be slower. -- Info here
@JohnHC - That is relevant if the second term of NVL requires any kind of evaluation. In this context it doesn't - DESIGNATION is evaluated already. Note also that NVL has been along much longer than COALESCE, and in some cases it may actually be faster.
@Dessma - What will happen if CIRCLE (for example) is NULL in the base table? Is that the desired result? (Probably not!)
1

LNNVL - descript how lnnvl evaluates values. != - it is correct. I've not do the mistake here.

Why lnnvl better from column_name = nvl(param,column_name) .

if column has null value and param has null value.

null = null => false this row will be exluded from result.

select * from table
where lnnvl(column_name1 != ?) 
  and lnnvl(column_name2 != ?)
  .
  .
  .

Comments

1

Using COALESCE:

SELECT *
FROM EMPLOYEE
WHERE COALESCE(DEPARTMENT,0) = COALESCE(:yourParam1,DEPARTMENT,0)
AND COALESCE(DESIGNATION,0) = COALESCE(:yourParam2,DESIGNATION,0)
AND COALESCE(DESIGNATION,0) = COALESCE(:yourParam3,DISTRICT,0)
AND COALESCE(DESIGNATION,0) = COALESCE(:yourParam4,CIRCLE,0)

Comments

1

The answer using Coalesce is genius. BUT, the zeroes need single quotes around them. Especially in this example were the parameters are likely to not be numbers, it will throw off the SQL because the actual field is a string but the 0 without quotes is a number. I applied this to my code and it worked like a charm. Recommendation:

    SELECT *
    FROM EMPLOYEE
    WHERE COALESCE(DEPARTMENT,'0') = COALESCE(:yourParam1,DEPARTMENT,'0')
    AND COALESCE(DESIGNATION,'0') = COALESCE(:yourParam2,DESIGNATION,'0')
    AND COALESCE(DISTRICT,'0') = COALESCE(:yourParam3,DISTRICT,'0')
    AND COALESCE(CIRCLE,'0') = COALESCE(:yourParam4,CIRCLE,'0')

Thank you so much, Mohammad Osman Gani Faisal!!!

1 Comment

Will just putting it in a NVL work e.g. WHERE NVL(department , '0') = NVL(:yourParam1 , '0') ?
0

Using decode:

SELECT *
FROM EMPLOYEE
WHERE decode(p_DEPARTMENT, NULL, 1, DEPARTMENT, 1, 0) = 1
    AND decode(p_DESIGNATION, NULL, 1, DESIGNATION, 1, 0) = 1
    AND decode(p_DISTRICT, NULL, 1, DISTRICT, 1, 0) = 1
    AND decode(p_CIRCLE, NULL, 1, CIRCLE, 1, 0) = 1

2 Comments

If p_CIRCLE = NULL won't this just exclude all the values for CIRCLE that are non-NULL rather than acting as an optional parameter and allowing any CIRCLE value?
@MT0 add changes

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.