views:

3424

answers:

5

I have a stored procedure in SQL Server 2000 that performs a search based on parameter values. For one of the parameters passed in, I need a different WHERE clause depending on its value - the problem is that the 3 values would be where MyColumn

  1. IS NULL
  2. IS NOT NULL
  3. ANY VALUE (NULL AND NOT NULL) (essentially no WHERE clause)

I'm having some mental block in coming up with the correct syntax. Is this possible to do in one select statement without performing some IF @parameter BEGIN ... END branching?

+8  A: 
WHERE (@myParm = value1 AND MyColumn IS NULL)
OR  (@myParm = value2 AND MyColumn IS NOT NULL)
OR  (@myParm = value3)

Someone else mentioned the CASE statement, this would go something like:

SELECT Field1, Field2 FROM MyTable
WHERE CASE @myParam
    WHEN value1 THEN MyColumn IS NULL
    WHEN value2 THEN MyColumn IS NOT NULL
    WHEN value3 THEN TRUE
END

EDIT:

I did a brief search and found this forum post which implies that the CASE statement is not usable in this way, so try it and if it doesn't work the first method may have to do.

Patrick McDonald
You had the same idea as I did. However, you do need the parentheses.
BobbyShaftoe
Thanks Bobby, updated my answer
Patrick McDonald
I'm not sure whether you do or don't *need* the parentheses, but I'm a big advocate of parentheses in complex boolean expressions. Not having them leaves it up to the compiler to do order-of-operations and is rather scary, if you ask me.
lc
I'd already tried the CASE statement, but CASE evaluates to one result expression, therefore evaluating to 'IS NULL', 'IS NOT NULL', 'myColumn IS NULL' etc does not work. Just testing your first answer now
Russ Cam
I also tried it and CASE doesn't work this way. My suggestion to use the CASE statement to solve this problem (see my answer) is therefore wrong.
Ronald Wildenberg
i didn't think about doing it like this. now i need to go and fix some of my stored procedures... thanks
DForck42
A: 

You should take a look at the CASE statement.

Ronald Wildenberg
Yeah, this is another good method.
BobbyShaftoe
I don't believe you can use the CASE statement in this scenario as CASE evaluates to one result expression
Russ Cam
It's not as straightforward as I thought it was in this case. You could add a case statement to your select clause that does the same as the OR-ed together WHERE clause but that would just give you a less readable SQL statement. I updated my answer to show this.
Ronald Wildenberg
Ok, that is also not going to work. CASE is just not the right choice for this kind of query...
Ronald Wildenberg
@rwwilden - I think you must have gone down the same mental route that I did!
Russ Cam
+4  A: 

You could just do something like this:

SELECT *
FROM foo
WHERE (@param = 0 AND MyColumn IS NULL)
OR (@param = 1 AND MyColumn IS NOT NULL)
OR (@param = 2)

Something like that.

BobbyShaftoe
A: 

COALESCE

WHERE MyColumn = COALESCE(@value,MyColumn)

If @value is NULL, it will compare MyColumn to itself, ignoring @value = no where clause.

IF @value has a value (NOT NULL) it will compare MyColumn to @value

Chad Grant
I don't believe you can use the CASE statement in this scenario as CASE evaluates to one result expression. COALESCE or even ISNULL I don't believe will work either.
Russ Cam
please review my edit, am I completely missing something in your question?
Chad Grant
@Deviant - I think your missing the question slightly. The WHERE clause on MyColumn needs to be set by another value because it does not directly relate to the parameter value i.e. if NULL is passed, then WHERE clause is negated. If any other value is passed, then the resultset will be only for WHERE MyColumn equals that value, not MyColumn having a known value. The WHERE clause of MyColumn having a NULLvalue is not addressed.
Russ Cam
This is how using COALESCE would work, which is not what I need
Russ Cam
+2  A: 

This is how it can be done using CASE:

DECLARE @myParam INT;
SET @myParam = 1;

SELECT * 
  FROM MyTable
 WHERE 'T' = CASE @myParam
             WHEN 1 THEN 
                CASE WHEN MyColumn IS NULL THEN 'T' END
             WHEN 2 THEN
                CASE WHEN MyColumn IS NOT NULL THEN 'T' END
             WHEN 3 THEN 'T' END;
onedaywhen