SQL CASE query condition - sql

I have the following condition in my stored procedure:
[DMO].[DriverModelName] =
CASE WHEN ISNULL(#driverModelName,'NotSet') = 'NotSet' THEN
[DMO].[DriverModelName]
ELSE
#driverModelName
END
This implies that when I pass 'NotSet' to varchar parameter #driverModelName, it should return all the rows but for some reason it's returning only those rows which has a value in column DriverModelName & omitting the null value rows.
Am I doing anything wrong here?

This is because NULL == NULL = FALSE, for the purpose of the WHERE clause, unless you set ANSI_NULLS to OFF. Example:
SET ANSI_NULLS OFF
IF NULL = NULL
PRINT 'TRUE'
ELSE
PRINT 'FALSE'
SET ANSI_NULLS ON
IF NULL = NULL
PRINT 'TRUE'
ELSE
PRINT 'FALSE'
The result is:
TRUE
FALSE
In order to get all rows, including the NULL values, you should use
(#driverModelName IS NULL OR [DMO].[DriverModelName] = #driverModelName)
For references:
http://www.sqlservercentral.com/blogs/steve_jones/2010/10/13/common-sql-server-mistakes-1320-equals-null/
SQL is null and = null
Why does NULL = NULL evaluate to false in SQL server
Additional Reading on Catch-All queries:
Catch-all Queries by Gail Shaw
The Curse and Blessings of Dynamic SQL by Erland Sommarskog

Well if [DMO].[DriverModelName] is ever NULL what are you expecting the result of this CASE be? Isn't this missing a ISNULL() around that column too?
ISNULL([DMO].[DriverModelName], 'NotSet') =
CASE WHEN ISNULL(#driverModelName,'NotSet') = 'NotSet' THEN
[DMO].[DriverModelName]
ELSE
#driverModelName
END
You cant say NULL = #someValue, it must be IS NULL or handle both sides with ISNULL()

Related

Update multiple values using IS NULL condition

I just finished migrating an Access database to the SQL Server and I need to fix the Yes/No values to be defaulted to No as their data type conversion is set to bit.
I do this by setting the default value to 0.
However, I want to execute a query to do that as well, but there are multiple bit rows.
I know how to use multiples with the SET command, but how do we use multiple with WHERE? What is the proper way of structuring it?
UPDATE sometable SET
[isConditionOnePassed] = 0
, [isSecondPassed] = 0
, [isThirdPassed] = 0
WHERE [isConditionOnePassed] IS NULL, [isSecondPassed] is NULL, [isThirdPassed] IS NULL
Or is it with an AND? Like boolean logic?
UPDATE sometable SET
[isConditionOnePassed] = 0
, [isSecondPassed] = 0
, [isThirdPassed] = 0
WHERE [isConditionOnePassed] IS NULL and [isSecondPassed] is NULL and [isThirdPassed] IS NULL
Hmmm . . . If you want to set NULL values to another value, you can use COALESCE():
UPDATE sometable
SET isConditionOnePassed = COALESCE(isConditionOnePassed, 0),
isSecondPassed = COALESCE(isSecondPassed, 0),
isThirdPassed = COALESDCE(isThirdPassed, 0)
WHERE isConditionOnePassed IS NULL OR isSecondPassed is NULL OR isThirdPassed IS NULL;
Seems like what you really need is an ISNULL or CASE expression. Here is an example with both:
UPDATE dbo.SomeTable
SET isConditionOnePassed = ISNULL(isConditionOnePassed,0),
isSecondPassed = CASE isSecondPassed WHEN 1 THEN 1 ELSE 0 END;

How to set optional parameter for int type variable

Have two variable StatusTypeTestID and StatusTestID want to set them as optional in where clause as like bellow,but optional option not work for int variable.
Note: default value for int variable is 0
DECLARE #StatusTypeTestID as int
SET #StatusTypeTestID = 1
DECLARE #StatusTestID as int
SET #StatusTestID = 0
select *
from LiveCustomerStatus
where (StatusType=#StatusTypeTestID
and (Status = #StatusTestID or #StatusTestID is null))
As you were already trying, you can check if your parameters have been set as null or if they match the correspondent field.
This way you can leave a parameter as null if you want it to be optional, not affecting the result.
select *
from LiveCustomerStatus
where (#StatusTypeTestID is null or StatusType=#StatusTypeTestID)
and (#StatusTestID is null or Status = #StatusTestID)
option(recompile)
I have added a option(recompile) clause that will force SQL Server to recompile the query at every execution. This way it will use the appropriate indexes to optimize it depending of the value of the parameters (wether they are null or not).
You can comment both set statements and below query will work:
select * from LiveCustomerStatus
where (#StatusTypeTestID is null or StatusType=#StatusTypeTestID)
and (#StatusTestID is null or Status = #StatusTestID)
Use CASE Statement in WHERE clause :
SELECT *
FROM LiveCustomerStatus
WHERE StatusType = CASE WHEN ISNULL(#StatusTypeTestID,'') = '' THEN
StatusType ELSE #StatusTypeTestID END
AND Status = CASE WHEN ISNULL(#StatusTestID,'')= '' THEN Status ELSE
#StatusTestID END

Select Logic in Query. Is this possible in Oracle?

Im trying to implement some sort of logic on the select statement of the query. I want it so that if no attribute is given, or if the inAttribute is 'NONE'; it will return the date and ALL of the values (compprice, compspread,price,spread,run).
If a value was given to in attribute then i want it to return the value it requested for (Refer to the case statement i tried to do).
Below is my attempt at it, and it is just not working. Any help please?
SELECT
mi.date,
IF inAttribute = '' THEN
mi.compprice,
mi.compspread,
mi.price,
mi.spread,
mi.run
ELSE
CASE inAttribute
WHEN 'CP' THEN mi.compprice,
WHEN 'CS THEN mi.compspread,
WHEN 'MP' THEN mi.price,
WHEN 'MS' THEN mi.spread,
WHEN 'R' THEN mi.run
END
END IF
FROM userValueTable mi
WHERE mi.index_family = inIdxFamily
AND mi.index_id = inIdxId
AND mi.date_>= inStartDate
AND mi.date_<= inEndDate
ORDER by mi.date_ ASC;
Few remarks You can't have variable column list from one line to another. '' is equal to NULL, comparing NULL with equality ( = ) is always false. you can have some fixed number of columns and set value of any column using CASE clause.
Oracle doesn't have an IF for SQL. Use CASE instead - it can act like a C/C#/Java/etc switch - case as you have it in your query, and it can also act like an if.
Also, as mentioned above:
You're stuck with returning a constant number of columns unless you use dynamic SQL
In Oracle, '' is treated as NULL so instead of = '' use IS NULL.
If you don't want to go to Dynamic SQL, you could add a "type" column to your select list and then null out any inapplicable values. Your downstream logic could pick the values to use (or ignore) based on the type. Here's an example:
SELECT
mi.date,
CASE
WHEN inAttribute IS NULL THEN 'inAttrNull'
ELSE 'inAttrNotNull'
END AS RecordType,
CASE WHEN inAttribute IS NULL THEN mi.compprice END AS compprice,
CASE WHEN inAttribute IS NULL THEN mi.compspread END AS compspread,
CASE WHEN inAttribute IS NULL THEN mi.price END AS price,
CASE WHEN inAttribute IS NULL THEN mi.spread END AS spread,
CASE WHEN inAttribute IS NULL THEN mi.run END AS run,
CASE inAttribute
WHEN 'CP' THEN mi.compprice
WHEN 'CS' THEN mi.compspread
WHEN 'MP' THEN mi.price
WHEN 'MS' THEN mi.spread
WHEN 'R' THEN mi.run
END AS SpecialValue
FROM userValueTable mi
... and your WHERE and ORDER BY clauses
You'll get a result set something like this:
RecordType compprice compspread price spread run specialvalue
------------- ---------- ---------- ---------- ---------- ---------- ------------
inAttrNotNull (null) (null) (null) (null) (null) 1234.56
inAttrNull 111.11 222.22 333.33 444.44 555.55 (null)
I know this isn't what you wanted, but it may be something you can work with as an alternative.
There is no IF in Oracle SQL, only in PL/SQL. You have to rewrite it to CASE. The same as you did in your query in ELSE part (you missed a single closing quote after 'CS' THEN...).
SELECT ...
(CASE WHEN inAttribute IS NULL THEN mi.compprice
WHEN .... THEN...
WHEN .... THEN...
...
ELSE ...
END) AS some_column_alias
FROM ...

CASE Statement in where clause using equal to and IN

WHERE CONDITION1='ABC'
AND Status =
CASE #Option
WHEN 1 THEN 'True'
WHEN 2 THEN 'False'
WHEN 3 THEN NULL
WHEn 4 THEN **IN ('True', 'False', NULL)**
END
How do I write a query where my first options match directly using = but my last option needs an IN
The above query gives error, but I want something similar to it, which I am not able to find out.
A CASE statement can't return a set of values... but this query should give you the same results:
WHERE CONDITION1='ABC'
AND Status =
CASE
WHEN 1 THEN 'True'
WHEN 2 THEN 'False'
WHEN 3 THEN NULL
WHEN 4 THEN Status
END
Also, note that unless you have ANSI_NULLS OFF, Status will never = NULL... you would need to use IS NULL for this comparison, and you'd need to forgo the CASE statement altogether.
Skip the CASE statement and use OR. And as per ANSI standard don't compare with NULL:
WHERE CONDITION1='ABC'
AND ((#Option = 1 AND Status = 'True') OR
(#Option = 2 AND Status = 'False') OR
(#Option = 3 AND Status IS NULL) OR
(#Option = 4 AND (Status IS NULL OR Status IN ('True', 'False'))))

Update of column happens even though I don't want it to happen

I've got a case statement:
UPDATE
Answer
SET
AnswerID = #AnswerID,
AnsweredBy = CASE WHEN LEN(#AnsweredBy) > 0 THEN #AnsweredBy END
Even when #AnsweredBy is NULL it still sets the AnsweredBy column to null.
I've tried to test for null as well by doing this:
UPDATE
Answer
SET
AnswerID = #AnswerID,
AnsweredBy = CASE WHEN #AnsweredBy IS NOT NULL THEN #AnsweredBy END
Meaning I do not want to update the answeredby column unless there is a value.
Even in my C# code I do not pass a value to my stored procedure:
if (answeredBy.Length > 0)
cmdSelect.Parameters.Add("#AnsweredBy", SqlDbType.VarChar).Value = answeredBy;
unless there is a value. And in my sproc I default that column variable to null:
#RunoffAnswerID bigint,
#AnswerID varchar(3)=NULL,
#AnsweredBy varchar(50)=NULL,
So my question is how do I perform the rest of my updates, because there are about 5-10 more columns but only update the answeredby if there is a value in #AnsweredBy?
SET AnsweredBy = ISNULL(#AnsweredBy, AnsweredBy)
UPDATE
Answer
SET
AnswerID = #AnswerID,
AnsweredBy = CASE WHEN LEN(#AnsweredBy) > 0 THEN #AnsweredBy ELSE AnsweredBy END