bit datatype in where condition - sql

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.

Related

SQL Server - Using CASE statement

I have a SELECT statement with a WHERE clause that I want to dynamically change depending if a parameter is supplied or not.
I can't seem to understand how to use CASE statement in a WHERE clause but this is how I want it to look like using an IF statement.
DECLARE #Gender NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
DECLARE #Status NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
SELECT Name
FROM Person
WHERE
-- first WHERE clause
IF #Gender IS NULL
BEGIN
Gender IS NULL
END
ELSE
BEGIN
Gender = #Gender
END
AND
-- second WHERE clause
IF #Status IS NULL
BEGIN
Status IS NULL
END
ELSE
BEGIN
Status LIKE '%' + #Status + '%'
END
Is it possible to transform this code into a CASE statement?
I think you want:
select p.name
from person p
where ( (#gender is null and gender is null) or gender = #gender) and
( (#status is null and status is null) or status = #status);
Note that this does "null-matching". Often, people want to use NULL to select all records, not just the NULL ones. If that is what you intend, then:
select p.name
from person p
where ( #gender is null or gender = #gender) and
( #status is null or status = #status);
In either situation, case is not needed in the where. As a general rule, don't use case in where -- unless you really need it to control the order of evaluation of expressions.
You can do this:
SELECT Name
FROM Person
WHERE Gender = COALESCE(#gender, Gender)
AND (#Status is null or Status like '%' + #status + '%')
DECLARE #Gender NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
DECLARE #Status NVARCHAR(100) = NULL --this is an INPUT parameter and may or may not be NULL
SELECT Name
FROM Person
WHERE CASE WHEN #Gender IS NULL THEN 1
WHEN #Gender = ISNULL(Gender, '') THEN 1
ELSE 0
END = 1
AND CASE WHEN #Status IS NULL THEN 1
WHEN ISNULL(Status, '') LIKE '%' + #Status + '%' THEN 1
ELSE 0
END = 1

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

How to condition my select based on boolean parameter

I'm creating a stored procedure that should return a list of users based on a boolean flag #status as follows:
If status is not informed, the query must return all users
If 'status' is passed as true, the query must return only users where the column LastAccess is not null.
If status is passed as false, the query must return users which column LastAccess is null.
This column is of type datetime.
I'm ok dealing the first use case, with #status is null in the last line of the following code:
CREATE PROCEDURE selectUsersByStatus (
#userId int,
#status bit
)
AS
SELECT * from users
WHERE users.id = #userId
and (#status is null or CASE #status WHEN 1 THEN (users.LastAccess is not null) ELSE (users.LastAccess is null))
However the rest of the line obviously doesn't work. How to proceed?
Thanks
Try simple:
CREATE PROCEDURE selectUsersByStatus (
#userId int,
#status bit
)
AS
SELECT * from users
WHERE users.id = #userId
and (#status is null OR (#status = 1 AND users.LastAccess IS NOT NULL) OR (#status = 0 AND users.LastAccess IS NULL))

Optional Arguments in WHERE Clause [duplicate]

This question already has answers here:
Stored Procedure with optional "WHERE" parameters
(6 answers)
Closed 4 years ago.
Lets suppose there is a stored procedure that has 3 params. Out of all the possibilities, I'm looking to achieve this with a single WHERE clause without getting out of control with using () AND () OR () too much...
Example:
//Params
#CITY VARCHAR(100) = NULL,
#GENDER VARCHAR(100) = NULL,
#AGE VARCHAR(100) = NULL
I suppose you can do it using IF BEGIN ... END for each Variable if Exists, but that makes the code alot longer than desired..
This method below won't work because its way too long (there are about 10 different fields like this, but the example is only 3.) and i'm not sure if it even directly pulls up distinctive values...
SELECT NAME FROM TABLE
WHERE (
(CITY=#CITY AND GENDER=#GENDER AND AGE=#AGE)
OR (CITY=#CITY AND GENDER=#GENDER)
OR (GENDER=#GENDER AND AGE=#AGE)
OR (CITY=#CITY AND AGE=#AGE)
OR (CITY=#CITY)
OR (GENDER=#GENDER)
OR (AGE=#AGE)
)
Is there an even shorter more efficient way to do this?
If yes, it is preferable for the method to be compatible with JOIN's also.
Alternatively to the ISNULL / COALESCE options, you can test the parameters for being null:
SELECT NAME
FROM TABLE
WHERE
(#City IS NULL OR City = #City)
AND
(#Gender IS NULL OR Gender = #Gender)
AND
(#Age IS NULL OR Age = #Age)
what about this?
SELECT
NAME
FROM TABLE
WHERE CITY = COALESCE(#CITY, CITY)
AND GENDER = COALESCE(#GENDER, GENDER)
AND AGE = COALESCE(#AGE, AGE)
Try something like this:
SELECT NAME
FROM TABLE
WHERE
City = IsNull(#City, City) AND
Gender = IsNull(#Gender, Gender) AND
Age = IsNull(#Age, Age)
OR:
SELECT NAME
FROM TABLE
WHERE
(City = #City OR #City IS NULL) AND
(Gender = #Gender OR #Gender IS NULL) AND
(Age = #Age OR #Age IS NULL)
SELECT NAME
FROM TABLE
WHERE
City = case when isnull(#City ,'') = '' then City
else #City end
AND
Gender = case when isnull(#Gender ,'') = '' then Gender
else #Gender end
AND
Age = case when isnull(#Age ,0) = 0 then Age
else #Age end
Possibly this:
create procedure myProc
--Params
#CITY VARCHAR(100) = NULL,
#GENDER VARCHAR(100) = NULL,
#AGE VARCHAR(100) = NULL
as
SELECT NAME FROM [TABLE]
WHERE ISNULL(CITY,'')=ISNULL(#CITY,ISNULL(CITY,''))
AND ISNULL(GENDER,'')=ISNULL(#GENDER,ISNULL(GENDER,''))
AND ISNULL(AGE,'')=ISNULL(#AGE,ISNULL(AGE,''))
go
Assuming the columns in the WHERE clause are nullable, using ISNULL to avoid null comparison.

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.