Difference between ColumnName = Null and ColumnName Is Null in SQL Server [duplicate] - sql

This question already has answers here:
Why doesn't SQL support "= null" instead of "is null"?
(12 answers)
Closed 9 years ago.
What is the difference between ColumnName = Null and ColumnName Is Null in SQL Server? I have researched about this but I didn't get any clarification.
Actually I want to retrieve column has null value
Select * from Table1 where column1 is null
This query returning expected result but the following query not giving
Select * from Table1 where column1 = null

Comparisons with null using normal operators are never true.
That's basically because null is "unknown" so it can't be determined whether it is or is not some value.
The special syntax is null and is not null must be used to determine nullness.

Using comparison operators on NULL will result un Unkown result
Take a look at the following example:
Declare #temp table
(
val1 int,
val2 int
)
INSERT INTO #temp
VALUES (1,NULL),
(NULL,1),
(NULL,NULL)
SELECT CASE
WHEN val1 > val2 THEN 'Val 1 greater'
WHEN val2 > val1 THEN 'val 1 smaller'
WHEN val1 = val2 THEN 'Val1 is equal to val 2'
WHEN val1 = NULL THEN 'val1 = NULL'
WHEN val1 IS NULL THEN 'val1 IS NULL'
ELSE 'Unknown'
END result
FROM #temp
this will result:
Unknown
val1 IS NULL
val1 IS NULL
Please note that changing the ANSI_NULLS to OFF, will change the behaviour of the = operator, and will return TRUE for NULL = NULL
Any way, IMHO (and I think the prevailing view is), The best practice is using IS NULL

"is null" is the proper way. It's like the difference between <> and != for not equal. != is the standard.
here is the Microsoft documentation: http://technet.microsoft.com/en-us/library/ms188795.aspx
"To determine whether an expression is NULL, use IS NULL or IS NOT NULL instead of comparison operators (such as = or !=). Comparison operators return UNKNOWN when either or both arguments are NULL."

Related

Force COALESE(NULL,NULL) to return NULL

In SQL SERVER
Considering the fact that:
Col1 and Col2 contain numeric and NULL values
SELECT
COALESCE(Col1,Col2)
Return an error: "At least one of the arguments to COALESCE must be an expression that is not the NULL constant."
Considering that Col1 and Col2 are NULL,I want to force it to return NULL value in this case.
The workaround seems to be unelegant/inefficient for me:
SELECT
NULLIF(COALESCE(Col1 ,Col2 ,''),'')
Note that Col1 and Col2 are numeric fields and cannot take '' as a value.
Any other suggestion ?
Thank you for your help
This code works:
SELECT COALESCE(Col1, Col2)
FROM . . . -- references here that define COL1 and COL2
If both columns are NULL, it will return NULL (typed as an integer in your case).
The only time you get the error you mention is when the columns are explicitly NULL. Even calculations seem to get around this:
select coalesce(null + 3, null)
--> NULL rather than an error
The following even returns NULL rather than an error:
declare #col1 int;
declare #col2 int;
select coalesce(#col1, #col2);
Here is a db<>fiddle.

NULL value in where clause

In stored procedure I have this query
DECLARE #BadRowsCount int;
SET #BadRowsCount = 0;
SELECT #BadRowsCount = COUNT(*)
FROM #ImportTemp
WHERE #ImportTemp.Status <> 'A' AND #ImportTemp.Status <> 'B'
And #BadRowsCount if in #ImportTemp.Status are values different than A or B has positive value that is ok.
But if in #ImportTemp.Status is NULL #BadRowsCount is 0.
Why? NULL isn't different than A or B?
Status is defined as:
[Status] [varchar](80) NULL
I must define WHERE clause like:
WHERE (#ImportTemp.Status <> 'A' AND #ImportTemp.Status <> 'B') OR #ImportTemp.Status is NULL
?
By default, in SQL Server, comparison operators return UNKNOWN (i.e. not true or false) if either value is a null.
MSDN IS [NOT] NULL documentation
There are ways to change how SQL Server handles null comparisons with things like SET ANSI_NULLS. Definitely pay attention to upcoming changes to the default for this value.
Here is an interesting article which covers several issues related to null handling.
Because the not equal operator (<>) is, like most operators, not NULL save. That means it results in unknown when comparing with NULL.

Oracle/PL SQL/SQL null comparison on where clause

Just a question about dealing will null values in a query.
For example I have the following table with the following fields and values
TABLEX
Column1
1
2
3
4
5
---------
Column2
null
A
B
C
null
I'm passing a variableY on a specific procedure. Inside the procedure is a cursor like this
CURSOR c_results IS
SELECT * FROM TABLEX where column2 = variableY
now the problem is variableY can be either null, A, B or C
if the variableY is null i want to select all record where column2 is null, else where column2 is either A, B or C.
I cannot do the above cursor/query because if variableY is null it won't work because the comparison should be
CURSOR c_results IS
SELECT * FROM TABLEX where column2 IS NULL
What cursor/query should I use that will accomodate either null or string variable.
Sorry if my question is a bit confusing. I'm not that good in explaining things. Thanks in advance.
Either produce different SQL depending on the contents of that parameter, or alter your SQL like this:
WHERE (column2 = variableY) OR (variableY IS NULL AND column2 IS NULL)
Oracle's Ask Tom says:
where decode( col1, col2, 1, 0 ) = 0 -- finds differences
or
where decode( col1, col2, 1, 0 ) = 1 -- finds sameness - even if both NULL
Safely Comparing NULL Columns as Equal
You could use something like:
SELECT * FROM TABLEX WHERE COALESCE(column2, '') = COALESCE(variableY, '')
(COALESCE takes the first non NULL value)
Note this will only work when you the column content cannot be '' (empty string). Else this statement will fail because NULL will match '' (empty string).
(edit)
You could also consider:
SELECT * FROM TABLEX WHERE COALESCE(column2, 'a string that never occurs') = COALESCE(variableY, 'a string that never occurs')
This will fix the '' fail hypothesis.
Below is similar to "top" answer but more concise:
WHERE ((column2 = variableY ) or COALESCE( column2, variableY) IS NULL)
May not be appropriate depending on the data you're looking at, but one trick I've seen (and used) is to compare NVL(fieldname,somenonexistentvalue).
For example, if AGE is an optional column, you could use:
if nvl(table1.AGE,-1) = nvl(table2.AGE,-1)
This relies on there being a value that you know will never be allowed. Age is a good example, salary, sequence numbers, and other numerics that can't be negative. Strings may be trickier of course - you may say that you'll never have anyone named 'xyzzymaryhadalittlelamb" or something like that, but the day you run with that assumption you KNOW they'll hire someone with that name!!
All that said: "where a = b or (a is null and b is null)" is the traditional way to solve it. Which is unfortunate, as even experienced programmers forget that part of it sometimes.
Try using the ISNULL() function. you can check if the variable is null and if so, set a default return value. camparing null to null is not really possible. remember: null <> null
WHERE variableY is null or column2 = variableY
for example:
create table t_abc (
id number(19) not null,
name varchar(20)
);
insert into t_abc(id, name) values (1, 'name');
insert into t_abc(id, name) values (2, null);
commit;
select * from t_abc where null is null or name = null;
--get all records
select * from t_abc where 'name' is null or name = 'name';
--get one record with name = 'name'
You could use DUMP:
SELECT *
FROM TABLEX
WHERE DUMP(column2) = DUMP(variableY);
DBFiddle Demo
Warning: This is not SARG-able expression so there will be no index usage.
With this approach you don't need to search for value that won't exists in your data (like NVL/COALESCE).

Dynamic where clause with set number of columns

I am bringing in arguments from an arbitrary source and there may be 1,2 or 3 args passed that need to go as a where clause in an sql query.
How can I write this query so no matter what args are passed the query will run with as many args as it can. I was thinking:
Passed in: x=1,y=null,z=5
//Do some simple checks and assign local variables when the value are not null.
if(arg == null)
{
arg = (/*some wild card that allows any value to be returned*/)
}
else{
arg = arg
}
Generated clause: WHERE X=localx AND Y=(ANY VALUE) AND Z=localz
What can I use for Y in this example so I can avoid dynamically creating a string with a variable amount of args? I found myself having a really hard time trying to articulate this problem.
I'm going to assume SQL Server. Use the ISNULL command and make all incoming parameters null when not provided.
SELECT *
FROM Table
WHERE ISNULL(#Param1,Field1)=Field1
AND ISNULL(#Param2,Field2)=Field2
AND ISNULL(#Param3,Field3)=Field3
AND ISNULL(#Param4,Field4)=Field4
AND ISNULL(#Param5,Field5)=Field5
A better solution, if any of the fields might have NULL values is:
SELECT *
FROM Table
WHERE (#Param1 is null or #Param1 = Field1) and
(#Param2 is null or #Param2 = Field2) and
(#Param3 is null or #Param3 = Field3) and
(#Param4 is null or #Param4 = Field4) and
(#Param5 is null or #Param5 = Field5)
The main difference between this and the solution that uses isnull is that this version handles NULL values in the fields. The expression isnull(#param1, field1) = field1 returns false when #param1 is NULL and field1 is NULL. The expression #Param1 is null or #Param1 = Field1 returns true when both are NULL.

NVL in Where clause doesn't return records which has null values

I used this SELECT statement:
SELECT
ID
,SUB_TYPE
,SERVICE_ID
,MENU_TYPE
,MENU_DESCRIPTION
FROM MY_TABLE
WHERE SUB_TYPE = NVL('' , SUB_TYPE)
AND SERVICE_ID = NVL('' , SERVICE_ID)
AND MENU_TYPE = NVL('' , MENU_TYPE)
The rows that have null MENU_TYPE don't return , but I want these records to return
Thanks in advance
NULL is never equal to NULL. And in Oracle, '' is NULL.
Try this:
((:P_MENU_TYPE IS NULL AND MENU_TYPE IS NULL) OR MENU_TYPE = :P_MENU_TYPE)
(I put a bind variable :P_MENU_TYPE where you had '' because the SQL wouldn't make sense with ''!)
If what you really mean is, MENU_TYPE must match the parameter if the parameter is not null, and may be anything including null when the parameter is null then simply:
(:P_MENU_TYPE IS NULL OR MENU_TYPE = :P_MENU_TYPE)
Are you looking for rows in which all three columns are null? If so, you want:
WHERE SUB_TYPE is null
AND SERVICE_ID is null
AND MENU_TYPE in null