I need to show a set of string into new column based on some columns value.
I tried to use isnull (name, variable = ''null) but does not work
DECLARE #NAME VARCHAR (MAX)
DECLARE #TEL VARCHAR (MAX)
SET #NAME = '- inNAME '
SET #TEL = '- inTEL '
SELECT IIF(NAME IS NULL, #NAME = '- notinNAME'), IIF(TEL IS NULL, #TEL = '- notinTEL;), (#NAME+ #TEL) AS RESULT FROM ADDRESS
NAME TEL RESULT
NULL 07 - notinNAME - inTEL
ARK NULL - inNAME - notinTEL
ARK 07 - inNAME - inTEL
NULL NULL - notinNAME - notinTEL
Is this what you are trying to do?
SELECT CONCAT(CASE WHEN NAME IS NULL THEN '- notinNAME' ELSE '' END,
CASE WHEN TEL IS NULL THEN '- notinTEL' ELSE '' END
)
FROM ADDRESS;
You cannot use variables for a few reasons. First, SQL Server does not allow you to assign variables in a SELECT and also to return values.
More importantly, SQL (in general) does not guarantee the order of evaluation of expressions in the SELECT. Your formulation assumes a particular order of evaluation, so it is not going to work.
EDIT:
If you want to use the variables:
SELECT CONCAT(CASE WHEN NAME IS NULL THEN #NAME ELSE '' END,
CASE WHEN TEL IS NULL THEN #TEL ELSE '' END
)
FROM ADDRESS;
Related
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
This question already has answers here:
CASE in WHERE, SQL Server
(5 answers)
Closed 4 years ago.
I'm creating a query (to eventually be used in a stored procedure) with multiple variations on what criteria is entered in a form. Sometimes there can be an entry, sometimes not. Sometimes the data field has a value, sometimes it's NULL.
The fields in my form are NAME, SSN, and DRLICENSE.
DECLARE #name VARCHAR(30);
DECLARE #ssn VARCHAR(10);
DECLARE #drlic VARCHAR(10);
--(if for example, someone enters data in two of the fields like this...)
SET #name = 'SMITH'
SET #drlic = 'D'
(In stored procedure)
SET #name = #name + '%'
SET #ssn = #ssn + '%'
SET #drlic = #drlic + '%'
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
NAME LIKE CASE WHEN LEN(#name) > 1 THEN #name ELSE NAME END
AND SSN LIKE CASE WHEN len(#ssn) > 1 THEN #ssn ELSE SSN END
AND DRLICENSE LIKE CASE WHEN LEN(#drlic) > 1 THEN #drlic ELSE DRLICENSE END
The idea behind my case statement is to check the variable for usage and perform a like if the name, ssn, or drlicense are partial entries.
My question is: how do I account for the case of NULL in the table column (i.e. SSN LIKE SSN does not work when SSN is NULL because SSN IS NULL needs to be there).
This isn't going to perform well, especially since you are using LIKE but parentheses are important here
where ((#name is null or name like '%' + #name + '%') or ( name is null))
and ((#ssn is null or ssn like '%' + #ssn + '%') or (ssn is null))
and ((#drlic is null or DRLICENSE like '%' + #drlic + '%') or (DRLICENSE is null))
This will return the NULL values in those columns regardless if a parameter is passed in or not. If you don't want the NULL then just remove the or ( name is null)) section from each line. I wasn't certain from your post.
if length(#foo) <= 1
set #foo = NULL
if length(#bar) <= 1
set #bar = NULL
...
WHERE (#foo is NULL or t.foo = #foo)
AND (#bar is NULL or t.bar like #bar)
OPTION (RECOMPILE)
This should do it:
WHERE (#name IS NULL OR name LIKE #name + '%')
AND (#ssn IS NULL OR ssn LIKE #ssn + '%')
AND (#drlic IS NULL OR drlicense LIKE #drlic + '%')
Note that if, for example, user searched for name = foo then it will return rows that match foo% and not rows that have NULL name.
You can inline adding the wild card to the parameter value and add your null checks inline as well. There is no need for a CASE statement either. For each of the parameter/column values the result returns true if the parameter is null or if the column value is null or if the column value starts with the passed in parameter value.
Where statement:
WHERE (Name IS NULL OR #name IS NULL OR Name LIKE #name + '%')
AND (SSN IS NULL OR #ssn IS NULL OR SSN LIKE #ssn + '%')
AND (DRLICENSE IS NULL OR #drlic IS NULL OR DRLICENSE LIKE #drlic + '%')
The key here is to not do any filtering if the incoming value to use is null or if the column value is null which I assume you do not want filtered on if it is null.
You could use ISNULL() it's very useful in cases like yours.
SELECT
NAME,
SSN,
DRLICENSE
FROM
TABLE
WHERE
ISNULL(NAME,0) LIKE ISNULL(ISNULL(#name, NAME),0)
AND ISNULL(SSN,0) LIKE ISNULL(ISNULL(#ssn, SSN),0)
AND ISNULL(DRLICENSE,0) LIKE ISNULL(ISNULL(#drlic, DRLICENSE),0)
This method will replace the NULL values with the column value if the column value is NULL then both will be set to 0 (which will be 0=0, which will always be true).
If I understand correctly, you want a NULL-safe equality. That is, you want NULL to match NULL and values to match values. So:
where (name = #name or (name is null and #name is null)) and
(ssn = #ssn or (ssn is null and #ssn is null)) and
(drlicense = #drlicense or (drlicense is null and #drlicense is null))
or, an intriguing variant:
where (select count(*)
from (select distinct *
from (values (name, 'name'), (#name, 'name'), (ssn, 'ssn'), (#ssn, 'ssn'), (drlicense, 'drlicense'), (#drlicense, 'drlicense')
v(val, which)
) x
) = 3
This is using group by semantics to combine NULL values.
Or, if you want some obfuscation:
where nullif(name, #name) is null and nullif(#name, name) is null and
nullif(ssn, #ssn) is null and nullif(#ssn, ssn) is null and
nullif(drlicense, #drlicense) is null and nullif(#drlicense, drlicense) is null
I want to select records from a table in a stored procedure. Given parameters can be empty or a string including some keys separated by comma (1, 2, etc)
I want to manage that when a parameter is an empty string, "WHERE" ignore searching.
I'm using this code:
where (CASE when #PatientID <> 0 then ( dental.ID_Sick in (1,2)) else (1=1) end)
Something like that is working in W3School. I mean:
SELECT * FROM Customers
WHERE (case when 1=1 then (Country IN ('Germany', 'France', 'UK')) else 1=1 end);
What is the problem in my query that does not work? SQLServerManagementStudio is giving error on "IN" statement.
Solution:
The best way to handle such optional parameters is to use dynamic SQL and built the query on the fly. Something like....
CREATE PROCEDURE myProc
#Param1 VARCHAR(100) = NULL
,#Param2 VARCHAR(100) = NULL
,#Param3 VARCHAR(100) = NULL
,#ListParam VARCHAR(100) = NULL
--, etc etc...
AS
BEGIN
SET NOCOUNT ON;
Declare #Sql NVARCHAR(MAX);
SET #Sql = N' SELECT *
FROM TableName
WHERE 1 = 1 '
-- add in where clause only if a value was passed to parameter
+ CASE WHEN #Param1 IS NOT NULL THEN
N' AND SomeColumn = #Param1 ' ELSE N'' END
-- add in where clause a different variable
-- only if a value was passed to different parameter
+ CASE WHEN #Param2 IS NOT NULL THEN
N' AND SomeOtherColumn = #Param3 ' ELSE N'' END
-- List Parameter used with IN clause if a value is passed
+ CASE WHEN #ListParam IS NOT NULL THEN
N' AND SomeOtherColumn IN (
SELECT Split.a.value(''.'', ''VARCHAR(100)'') IDs
FROM (
SELECT Cast (''<X>''
+ Replace(#ListParam, '','', ''</X><X>'')
+ ''</X>'' AS XML) AS Data
) AS t CROSS APPLY Data.nodes (''/X'') AS Split(a) '
ELSE N'' END
Exec sp_executesql #sql
, N' #Param1 VARCHAR(100), #Param2 VARCHAR(100) ,#Param3 VARCHAR(100) ,#ListParam VARCHAR(100)'
, #Param1
, #Param2
,#Param3
, #ListParam
END
Problem with Other approach
There is a major issue with this other approach, you write your where clause something like...
WHERE ( ColumnName = #Parameter OR #Parameter IS NULL)
The Two major issues with this approach
1) you cannot force SQL Server to check evaluate an expression first like if #Parameter IS NULL, Sql Server might decide to evaluate first the expression ColumnName = #Parameterso you will have where clause being evaluated even if the variable value is null.
2) SQL Server does not do Short-Circuiting (Like C#), even if it decides to check the #Parameter IS NULL expression first and even if it evaluates to true, SQL Server still may go ahead and evaluating other expression in OR clause.
Therefore stick to Dynamic Sql for queries like this. and happy days.
SQL Server does not have a Bool datatype, so you can't assign or return the result of a comparison as a Bool as you would in other languages. A comparison can only be used with IF-statements or WHERE-clauses, or in the WHEN-part of a CASE...WHEN but not anywhere else.
Your specific example would become this:
SELECT * FROM Customers
WHERE 1=1 OR Country IN ('Germany', 'France', 'UK')
It would be better readable to rewrite your statement as follows:
WHERE #PatientID = 0
OR dental.ID_Sick in (1,2)
Referring to your actual question, I'd advise to read the linked question as provided by B House.
May be this straight way will work for you
IF (#PatientID <> 0)
BEGIN
SELECT * FROM Customers
WHERE Country IN ('Germany', 'France', 'UK')
END
try this:
WHERE 1=(CASE WHEN #PatientID <>0 AND dental.ID_Sick in (1,2) THEN 1
WHEN #PatientID =0 THEN 1
ELSE 0
END)
I have following procedure to track column changes in the table.
ALTER PROCEDURE [UpdateAddress]
#id bigint=0,
#fullname varchar(200)='',
#address varchar(200)='',
#city varchar(200)='',
#state varchar(200)=''
AS
declare #desc varchar(500);
BEGIN
DECLARE #MyTableVar table(
fullname varchar(200) NULL,
address varchar(200) NULL ,
city varchar(200) NULL ,
state varchar(200) NULL );
BEGIN
UPDATE [Address]
SET
fullname=#fullname,
address=#address,
city=#city,
state=#state
OUTPUT deleted.fullname,
deleted.address,
deleted.city,
deleted.state
INTO #MyTableVar
WHERE [Id]=#id
here i will get all columns which are updated and not updated. So we need to compare both like deleted.fullname and inserted.fullname . So, if I have 20 columns in a table, and only 2 columns i updated. without comparing , is there any way to get only updated columns using output clause?
Example: I have 20 columns. in that only fullname and address i updated. so i should get Fullname,Address changed. without any comparison. Is there any sql built-in function like updated_column()?
You can use scalar expressions in the output. So, you could represent "no change" as, say, NULL:
OUTPUT (case when inserted.fullname <> deleted.fullname then deleted.fullname end),
(case when inserted.address <> deleted.address then deleted.address end),
(case when inserted.city <> deleted.city then deleted.city end),
(case when inserted.state <> deleted.state then deleted.state end)
This is unambiguous if the previous column values are never NULL.
You could also use the same idea to list together the columns that are changed:
OUTPUT deleted.fullname,
deleted.address,
deleted.city,
deleted.state,
((case when inserted.fullname <> deleted.fullname then 'fullname;' else '' end) +
(case when inserted.address <> deleted.address then 'address;' else '' end) +
(case when inserted.city <> deleted.city then 'city;' else '' end) +
(case when inserted.state <> deleted.state then 'state;' else '' end)
)
The expressions would be a bit more complicated to include NULL checks.
Iam writing an sql trigger with sql server
in this clause
IF (#EXON = '' OR #DATEDEB='' OR #DATEFIN= '') AND #N_CATComp =4
#DATEDEB #DATEFIN are datetime variable and the application accept null values for those both variable I want in this case null is not accepted , this works only for the first variable #EXON
plz help
IF (#EXON = '' OR ISNULL(#DATEDEB, '') ='' OR ISNULL(#DATEFIN, '') = '')
if it's null it'll return ''
To check if a variable #MyVar has it's value equal to null you should do this:
if (#MyVar IS NULL)
print '#MyVar has a NULL value'
else
print '#MyVar value is not NULL'
You should also check the documentation on the helper functions NULLIF and ISNULL.
IF (#EXON = '' OR #DATEDEB='' OR #DATEDEB IS NULL OR #DATEFIN= '' OR #DATEFIN IS NULL) AND #N_CATComp =4