what is the use of coalesce in sql? - sql

I'm new to sql server. I googled the use of coalesce and find out it is another words a replace of ISNULL.
I came across a piece of code posted in the forum about the different uses of coalesce.
use adventureworks
DECLARE #DepartmentName VARCHAR(1000)
SELECT #DepartmentName = COALESCE(#DepartmentName,'') + Name + ';'
FROM HumanResources.Department
WHERE (GroupName = 'Executive General and Administration')
SELECT #DepartmentName AS DepartmentNames
which return the result in a single line.
So why sql does not support string concatenation by default as in .NET like below?
DECLARE #DepartmentName VARCHAR(1000)
**SELECT #DepartmentName = #DepartmentName + Name + ';'**
FROM HumanResources.Department
WHERE (GroupName = 'Executive General and Administration')
SELECT #DepartmentName AS DepartmentNames
what is the use of coalesce in the below line
SELECT #DepartmentName = COALESCE(#DepartmentName,'') + Name + ';'
and why
**SELECT #DepartmentName = #DepartmentName + Name + ';'**
FROM HumanResources.Department
WHERE (GroupName = 'Executive General and Administration')
is not working?

coalesce simply returns the value of the 1st non-NULL argument in its parameter list.
e.g.
1.select coalesce(NULL,0,2,1);
will return 0 as 0 doesn't mean NULL.
2.select coalesce(id,emp_id,0) from tab1;
In this case attribute-id will be returned if it is NOT NULL otherwise if emp_id is NOT NULL emp_id will be returned else 0 will be returned.
In this case for concatenation you can simply use either +-operator or concat()-function. But here coalesce is used for the case when DepartmentName=NULL because if you concatenate or do some operation with NULL the result will be NULL. Hence to use blank(i.e. '') in place of NULL coalesce() has been used.
In this case coalesce has been used as DepartmentName is NULL at the moment when it is declared. Use the syntax Moho has given in his answer to substitute the use of coalesce.

add set #DepartmentName = '' after DECLARE #DepartmentName VARCHAR(1000) and you won't need the coalesce statement.
edit: updated after comment clarified things for me

COALESCE() returns the first non-null term. This code:
COALESCE(#DepartmentName,'')
means return a blank if the department name is null.
Concatenating a null with something gives a null, so if you don't use COALESCE() you'd lose the name value too.

COALESCE returns from a list of arguments the first expression that does not evaluate to NULL.
For your example COALESCE(#DepartmentName,'') this means that if #DepartmentName is NULL it shall return '' (an empty string) instead. This is needed because concatenating strings with a null value would return NULL.
SELECT 'test' + NULL -- will return NULL
COALESCE (Transact-SQL)

Related

Replace NULL with nulliff returns different query results

I'm trying to build a dynamic query, I will pass a parameter and if the parameter is empty, then the query returns all the items I have in the table. The second query returns all the items I have in the table. The first query returns a much shorter result.
Any ideas?
select ...
where table.code = isnull(nullif('',''),table.code)
select ...
where table.code = isnull(null,table.code)
This simple test shows the problem :
SELECT ISNULL(NULLIF('', ''), 'TEST')
Instead of returning TEST, as expected, it returns 'T', because the first NULLIF returns a null of varchar(1) type (the type of its parameters), so the return value of ISNULL is also casted to varchar(1).
I would simply use COALESCE instead of ISNULL (it doesn't try to convert the return value to the type of the first value) :
SELECT COALESCE(NULLIF('', ''), 'TEST')
This one returns the correct value 'TEST'.
So to fix your query you only need to replace ISNULL by COALESCE :
select ...
where table.code = coalesce(nullif('',''),table.code)
You can apply isnull() function twice as :
select ...
where table.code = isnull( isnull(null,#yourparam),table.code)
if #yourparam is null then isnull(null,#yourparam) returns null, too.
Let your parameter be denoted by #param that you supply in the query at runtime.
Your query could then be
declare #param varchar(50)
select * from table
where nullif(#param, '') is null or table.code = #param
for example see following two snippets, first query will return result only when there exists a table by the name you supplied, second query will return all records
declare #param varchar(50) = 'table_from_your_db'
select *
from information_schema.tables t
where nullif(#param, '') is null or t.table_name = #param
declare #param varchar(50) = ''
select *
from information_schema.tables t
where nullif(#param, '') is null or t.table_name = #param

When using CASE inside a WHERE clause, without ELSE, what is meant by NULL?

declare #Name varchar(45)
SELECT
*
FROM
table law
WHERE
--law.emp = case when isnumeric(#Name) = 1 then #Name else null end
law.emp = case when isnumeric(#Name) = 1 then #Name end
or coalesce(law.lname + ', ' + law.fname, '') like '%' + #Name + '%'
My question here is focusing on the CASE statement when it evaluates to something other than a numeric value...
If #Name is anything other than a numerical value, what is really happening? law.emp = null??? If so, it shouldn't return any results anyway, because the proper syntax is something like where law.emp is null, right?
So, just for clarification, my emp column doesn't actually contain any nulls.
I'm just trying to figure out what is really happening to my WHERE statement when #Name evaluates to something not numeric...
What actual evaluation is being done? Is SQL ignoring the condition?
That's kind of what I want: For SQL not to do anything with law.emp unless #Name is numeric. (I have other conditions that will use the #Name variable if it is text.)
The expression:
law.emp = NULL
always returns NULL. In a where clause, this is treated as false, and the row is not included in the result set.
I much prefer an explicit conversion:
law.emp = try_convert(int, #Name)
Or to whatever type emp is.

Understanding the Syntax for COALESCE

I am trying to understand the below syntax. Can I get some help with this.
DECLARE #StringList VARCHAR(2500);
SELECT COALESCE(#StringList + ',','') + CAST(apID as VARCHAR) AS ApIdList FROM testTable
As a result you will get all apID from testTable in VARCHAR
COALESCE
checks if first parameter is NULL then the second parameter will returned. In this line #StringList is always equals NULL
COALESCE(#StringList + ',','')
So, NULL + ',' = NULL and you will get empty string ('')
Then empty string + CAST(apID as VARCHAR) and you will get apID as VARCHAR
Coalesce returns the first non-null element provided in the list supplied. See - https://msdn.microsoft.com/en-us/library/ms190349.aspx.
In your case, if #StringList is not null, then it's contents will be prepended with a comma to appID for each row in testTable.
Your code is returning ApID as a string for all rows in the table. Why? Because #StringList is NULL so the first expression evaluates to '' and the second to a string representation of the ApId in some row in the table.
I caution you about the conversion to VARCHAR with no length. Don't do this! The default length varies by context, and you can introduce very hard-to-debug errors without a length.
A related expression is more common, I think:
SELECT #StringList = COALESCE(#StringList + ',', '') + CAST(apID as VARCHAR(8000)) AS ApIdList
FROM testTable;
This does string concatenation, so all the values of apID are concatenated together in a comma-delimited string.
What this is doing is looping on the result set to assign the variable. This type of assignment of a variable across multiple rows is discouraged. I don't think that SQL Server guarantees that it actually works (i.e. is a documented feature), but it appears to work in practice across all versions.

Comparing 2 variables in SQL stored procedure where 1 of them could be NULL [duplicate]

I must to check if two values, X and Y are different. If both are null, they must be considered as equal.
The unique way I found is:
select 1 as valueExists
where (#X is null and #Y is not null)
or (#Y is null and #X is not null)
or (#X <> #Y)
Is there a smart way to write this expression?
Thanks!
I think you could use COALESCE for that
WHERE coalesce(#X, '') <> coalesce(#Y, '')
What it does it returns an empty string if one of variables is null, so if two variables are null the two empty strings become equal.
I typically use a technique I picked up from here
SELECT 1 AS valuesDifferent
WHERE EXISTS (SELECT #X
EXCEPT
SELECT #Y)
WHERE EXISTS returns true if the sub query it contains returns a row. This will happen in this case if the two values are distinct. null is treated as a distinct value for the purposes of this operation.
You could try using NULLIF like this:
WHERE NULLIF(#X,#Y) IS NOT NULL OR NULLIF(#Y,#X) IS NOT NULL
You can use ISNULL
WHERE ISNULL(#X,'') <> ISNULL(#Y,'')

Select a column if other column is null

I need to select a field called ProgramID from a table and if the ProgramID is NULL then I need to select the value in the InterimProgramID from the same table and alias it as ProgramID.
How can I make a conditional SELECT statement to do this?
You need the ISNULL function.
SELECT ISNULL(a, b)
b gets selected if a is null.
Also, you can use the WHEN/THEN select option, lookup in BOL. Essentially: its c switch/case block meets SQL.
select COALESCE ( ProgramID , InterimProgramID ) as 'ProgramID'
You can use either the ISNULL function or the COALESCE function. They both do pretty much the same thing, however ISNULL only takes two parameters and COALESCE takes multiple parameters (returning the first non-null it encounters). Both try the first param, then the second, (and COALESCE continues on)
DECLARE #IAMNULL VARCHAR
DECLARE #IAMNOTNULL VARCHAR
SET #IAMNOTNULL = 'NOT NULL'
SELECT ISNULL(#IAMNULL, #IAMNOTNULL)
--Output: 'NOT NULL'
DECLARE #IAMNULLALSO VARCHAR
SELECT COALESCE(#IAMNULL, #IAMNULLALSO, #IAMNOTNULL)
--Output: 'NOT NULL'
SELECT ProgramID
FROM a_table
WHERE ProgramID IS NOT NULL
UNION
SELECT InterimProgramID AS ProgramID
FROM a_table
WHERE ProgramID IS NULL;
Coalesce('zzz-' + ProgramID, InterimID) as programID will still ignore ProgramID even if you have a pretext value. It's a cool little function
There is also:
Select NVL(Column_A, Column_B) From 'schema'.'table_name'
The NVL( ) function is available in Oracle, and not in MySQL or SQL Server. This function is used to replace NULL value with another value. It is similar to the IFNULL Function in MySQL and the ISNULL Function in SQL Server.
https://www.1keydata.com/sql/sql-nvl.html
You can also use IFNULL function
select IFNULL(ProgramId,interimId) as ProgramId