SQL Coalesce in WHERE clause - sql

I'm trying to implement optional parameters in a stored procedure that I have but I am running into a problem. Here's a simplified query to illustrate the issue:
SET ANSI_NULLS OFF
DECLARE #MiddleName VARCHAR(20);
SET #MiddleName = NULL;
SELECT * FROM [Customer]
WHERE [LastName] = 'Torres'
AND [MiddleName] = COALESCE(#MiddleName, [MiddleName])
When I run this query I need to get one row back because one Torres has NULL in the [MiddleName] column. But the query returns zero rows. Using IFNULL() produces the same result. From researching COALESCE, I was under the impression that NULL would be returned if all expressions are NULL. As I am not a SQL expert I assume that I am missing something, but what is it.....
Thanks in advance for any help.

The problem is that in sql, "WHERE Null = Null" will never return any rows since Null does not equal itself.
You have to do
SELECT * FROM [Customer]
WHERE [LastName] = 'Torres'
AND ( #MiddleName IS NULL OR [MiddleName] = #MiddleName )

You state you are looking for the query to return the row where the field MiddleName is NULL. Unfortunately (NULL = NULL) does not return true, it returns NULL.
You need something like...
SELECT * FROM [Customer]
WHERE [LastName] = 'Torres'
AND ([MiddleName] = #MiddleName OR #MiddleName IS NULL)

Are you trying to do this?
SELECT * FROM [Customer]
WHERE [LastName] = 'Torres'
AND ([MiddleName] = #MiddleName OR #MiddleName IS NULL)
From what I understand it looks like it.

Your COALESCE returns NULL when the #MiddleName parameter and the MiddleName column are both NULL, but the test will evaluate to false because a NULL does not equal any other NULL.
To workaround this you should explicitly test the #MiddleName parameter for nullity:
SELECT *
FROM [Customer]
WHERE [LastName] = 'Torres'
AND (#MiddleName IS NULL OR [MiddleName] = #MiddleName)

Related

SQL OR CONDITION ON TWO DIFFERENT COLUMNS

I have two fields (#EmployeeId,#SSOId) out of which one value can come or both can come, but when i am applying OR condition it is not giving me correct output. What i am doing wrong ?
ALTER PROCEDURE [dbo].[usp_User_GetDetails] (
#UserId INT = NULL
,#ADSId NVARCHAR(32) = NULL
,#EmployeeId NVARCHAR(32) = NULL
,#SSOId NVARCHAR(32) = NULL
,#UserName NVARCHAR(100) = NULL
)
AS
*/
SET NOCOUNT ON;
BEGIN
SELECT [USER_ID] AS UserId
,[FIRST_NM] AS FirstName
,[LST_NM] AS LastName
,[FULL_NM] AS FullName
,[ADS_USER_ID] AS ADSId
,[SEG_ID] AS SegmentId
,[PHONE_NO] AS PhoneNo
,[FAX_NO] AS FaxNo
,[EMP_ID] AS EmployeeId
,[EMAIL_AD_TX] AS Email
,[SSO_ID] AS SSOId
,[SFDC_IN] AS IsSFDC
,[USER_SFDC_ID] AS UserSFDCId
,[MGR_SFDC_ID] AS ManagerSFDCId
,[ACT_IN] AS IsActive
,[SYS_USER_IN] AS IsSystemUser
,[PORFOLIO_OWN_IN] AS CanHavePortfolio
,[MGR_ID] AS ManagerId
,[LST_LOG_IN_TS] AS LastLoginDate
,[EMP_BAND_TX] AS Band
,[CREAT_TS] AS CreatedDate
,[CREAT_BY_USER_ID] AS CreatedBy
,[LST_UPDT_TS] AS UpdatedDate
,[LST_UPDT_BY_USER_ID] AS UpdatedBy
FROM [dbo].[USER] WITH (NOLOCK)
WHERE ([EMP_ID] = ISNULL(#EmployeeId, [EMP_ID])OR [SSO_ID] = ISNULL(#SSOId, [SSO_ID])
AND [ADS_USER_ID] = ISNULL(#ADSId, [ADS_USER_ID])
AND [USER_ID] = ISNULL(#UserId, [USER_ID])
AND [FULL_NM] LIKE CASE
WHEN #UserName IS NOT NULL
THEN '%' + #UserName + '%'
ELSE [FULL_NM]
END
END
I don't think the parentheses are balanced correctly. In any case, I would write this without the ISNULL():
WHERE ((#EmployeeId IS NULL OR EMP_ID = #EmployeeId) OR
(#SSOId IS NULL OR SSO_ID = #SSOId)
) AND
(#ADSId IS NULL OR ADS_USER_ID = #ADSId) AND
(#UserId IS NULL OR USER_ID = #UserId) AND
(#UserName IS NULL OR FULL_NM LIKE '%' + #UserName + '%')
I am guessing that the OR is for the first two conditions. This is where the parens don't seem to line up in the query in the question.
I prefer this construct for two reasons. First, it handles NULL values in the column values as well as the parameter values. And second -- because it is more general -- it is one of the standard two ways I use to handle optional parameters (the other is to use dynamic SQL which can make use of indexes).
Query seems to be okay .Are you passing DBNull from you C# code or empty text
WHERE (#EmployeeId IS NULL OR (EMP_ID = #EmployeeId))
AND (#SSOId IS NULL OR (SSO_ID = #SSOId))
AND [ADS_USER_ID] = ISNULL(#ADSId, [ADS_USER_ID])
AND [USER_ID] = ISNULL(#UserId, [USER_ID])
AND [FULL_NM] LIKE CASE
WHEN #UserName IS NOT NULL
THEN '%' + #UserName + '%'
ELSE [FULL_NM]
Used this script
WHERE EMP_ID = CASE WHEN ISNULL(#EmployeeId,0) > 0 THEN #EmployeeId ELSE EMP_ID END AND SSO_ID = CASE WHEN ISNULL(#SSOId,0) > 0 THEN #SSOId ELSE SSO_ID END

bit datatype in where condition

I have column "Status" of bit type in a table and in the declaration of parameters I have defaulted it to 0 and I have few other parameters coming in with defaulted to null
#FirstName varchar(20) = null,
#LastName varchar(20) = null,
#Status bit = 0
and my sql is something like
Select * from customers where
(ISNULL(#FirstName,'') ='' OR FirstName= #FirstName)
AND (ISNULL(#LastName,'') ='' OR LastName= #LastName)
AND (Status = #Status)
The situation is if only #FirstName value is sent from the code and the Value of the column "Status = 1" in the table and no value for #Status is sent, then since it #Status defaults to 0 no records get returned. How to deal with the bit type, in a situation where the parameter for the bit type is not sent and the value for it in the table is 1.
You can set the default value of your #status parameter to null, as you have with your other parameters.
#Status bit = null
You can rationalise your filter by doing this
where
isnull(#firstname, Firstname) = FirstName
and
isnull(#LastName, LastName) = LastName
and
isnull(#Status, Status) = Status
Both this, and your original query, won't return rows where the value in the database is null.

Conditional stored procedure with bool values

I am trying to assemble a stored procedure to return a set of results.
On my page, I have three checkboxes and a searchbox.
Then in the stored procedure, I have this:
CREATE Procedure [dbo].[sp_Search]
#Bool1 bit = NULL,
#Bool2 bit = NULL,
#Bool3 bit = NULL,
#SearchTerm nvarchar(30)
As
Begin
Select
[CompanyID],
[CompanyName],
[Label],
[Bool1],[Bool2],[Bool3]
From [Contract Companies]
WHERE (CompanyName LIKE #SearchTerm OR [Label] LIKE #SearchTerm) AND
if(#Bool1 IS NOT NULL)
[Bool1] = 'True'
end
if(#Bool2 IS NOT NULL)
AND [Bool2] = 'True'
end
if(#Bool3 IS NOT NULL)
AND [Bool3] = 'True'
end
Something like that, with those three boolean values not true all the time, just when their checkbox will be checked.
How can I achieve that?
Thanks in advance, Laziale
You might try something like this:
create procedure [dbo].[sp_Search]
#Bool1 bit = null,
#Bool2 bit = null,
#Bool3 bit = null,
#SearchTerm nvarchar(30)
as
begin
select
CompanyID,
CompanyName,
Label,
Bool1,
Bool2,
Bool3
from Contract Companies
where (CompanyName like #SearchTerm or Label like #SearchTerm)
and (Bool1 = #Bool1 or #Bool1 is null)
and (Bool2 = #Bool2 or #Bool2 is null)
and (Bool3 = #Bool3 or #Bool3 is null)
end
This will get matching records for each bool when present, and all records otherwise.
It is noted that this may not be the best performing method of dynamically checking values, but they're bits here (often not indexed) and I think it fits very elegantly. There are alternatives discussed in that article.
Option with CASE expression
CREATE Procedure [dbo].[sp_Search]
#Bool1 bit = NULL,
#Bool2 bit = NULL,
#Bool3 bit = NULL,
#SearchTerm nvarchar(30)
As
Begin
Select
[CompanyID],
[CompanyName],
[Label],
[Bool1],[Bool2],[Bool3]
From [Contract Companies]
WHERE (CompanyName LIKE #SearchTerm OR [Label] LIKE #SearchTerm) AND
[Bool1] = CASE WHEN #Bool1 IS NOT NULL THEN 'True' ELSE [Bool1] END AND
[Bool2] = CASE WHEN #Bool2 IS NOT NULL THEN 'True' ELSE [Bool2] END AND
[Bool3] = CASE WHEN #Bool3 IS NOT NULL THEN 'True' ELSE [Bool3] END

Help with SQL Server query condition

I have the following query. but it gives me error in the in clause.
declare #lastName varchar(20)
set #lastName = 'Davis'
select *
from Table1
where Date >= '2013-01-09'
and lastname in(
case
when #lastName = 'DAvis' THEN #lastName
else 'Brown','Hudson' end)
Something like this:
select *
from Table1
where
Date >= '2013-01-09' and
(
(#lastName = 'Davis' and lastname = #lastName) or
(#lastName <> 'Davis' and lastname in ('Brown','Hudson'))
)
Interesting. I think in this case specifically it is the "'Brown','Hudson'" that is causing the issue. You would probably be best not using a case statement at all.
The problem is I don't know of a way to return multiple values in a single case so you have to do like Alex said and use simple boolean logic. You can use a case statement in your where clause however, just not to return multiple values in a single case.
If you want to filter results by three names, use following query:
declare #lastName varchar(20)
set #lastName = 'Davis'
select * from Table1
where Date >= '2013-01-09'
and lastname in(
'DAvis' ,'Brown','Hudson')

Null value column and NOT EXISTS T-sql

I'm trying to do the following:
IF NOT EXISTS (
SELECT *
FROM [tbl_web_company]
WHERE [name] = #name
AND [address1] = #address1
AND [address2] = #address2
AND [city] = #city
AND [province_id] = #province_id
AND [postal_code] = #postalcode
AND [contact_phone] = #phone
AND [contact_fax] = #fax
AND [deleted] = dbo.pvd_fn_getDeletedDate(#id, #active))
BEGIN
SELECT 'update'
END
ELSE
BEGIN
SELECT 'no update'
END
I'm basically trying to see if any of the columns have changed, but I'm having problems when #province_id and dbo.pvd_fn_getDeletedDate(#id, #active) are NULL in the database, and are both set as NULL.
Province ID is an INT - Nullable
Deleted is a Datetime - Nullable.
If the record in the database has NULL for both these values, then this will always select 'update'. Which is wrong as [province_id] and [deleted] are NULL.
Any suggestions how to handle NULLS in this case?
Can you use the ISNULL() function to set a default value?
SELECT *
FROM [tbl_web_company]
WHERE [name] = #name
AND [address1] = #address1
AND [address2] = #address2
AND [city] = #city
AND ISNULL([province_id],99999) = ISNULL(#province_id,99999)
AND [postal_code] = #postalcode
AND [contact_phone] = #phone
AND [contact_fax] = #fax
AND ISNULL([deleted], '1990-01-01') = ISNULL(dbo.pvd_fn_getDeletedDate(#id, #active), '1990-01-01')
BEGIN
SELECT 'update'
END
ELSE
BEGIN
SELECT 'no update'
END
Using ISNULL() prevents the optimizer from using indexes, so normally I'd advise against this, but the way this query is written, I'd be surprised if it's making use of an index anyway.
use
IS NULL
instead
= NULL
Use "IS NULL" instead:
SELECT 'Is null' WHERE NULL = NULL
woudn't return any rows, but:
SELECT 'Is null' WHERE NULL IS NULL
will...
A good reading about nulls here
As your values are coming from parameters and are not hard coded you can use the following:
...
AND ([province_id] IS NULL OR [province_id] = #province_id)
...
Use the same structure for your other NULLABLE fields.