Why #OpeningDate is getting saved as NULL even though I am doing this.
PROCEDURE [dbo].[InsertCaseANDHearingDetails]
#HearingDate datetime,
#IsOpeningDate bit= null,
#OpeningDate date= null,
AS
Begin
IF(#IsOpeningDate = 0)
Begin
Set #OpeningDate= (Select Convert(varchar, #HearingDate, 106))
End
Insert Into Hearings
values (#HearingDate, #OpeningDate)
End
Even though I am calculating it and hearing date is not null but why OpeningDate is getting saved as NULL.
#HearingDate != NULL will not work. The result of this comparison is always unknown. Use #HearingDate is not null instead.
Because the variable #HearingDate is not initialized, it would have a null value.
Also, the variable #OpeningDate wouldn't be set to Select Convert(varchar, #HearingDate, 106) because the if condition evaluates to unknown.
Hence, when you select values from the table they would be null.
Edit:
#IsOpeningDate bit= null
...
IF(#IsOpeningDate = 0)
This condition evaluates to unknown too as this is doing 0 = null. You cannot compare with null.
It will work if you use the following at the start of the Proc.
SET ANSI_NULLS OFF
Basically NULL can't be compared, not even with itself, because this is not a value. If at all, you want the engine to treat it as one, you need to set off the ANSI_NULLS property. That said, I would prefer to go with #vkp's answer any day.
Based on your edit, it looks like the below condition is not met:
IF(#IsOpeningDate = 0)
and hence, it remains NULL.
in the if condition why dont you check is null instead of comparing it to 0
Your query
IF(#IsOpeningDate = 0)
My suggestion
IF(#IsOpeningDate IS NULL)
Sorry it was my mistake to no mention parameters in Insert statement and since NULL were allowed so it inserted NULLs
Thanks for your help as it led me to figure out that what's actually going on.
Related
I have a stored procedure that includes a table variable which updates from other table variables. ISNULL() is not working in the below code. It returns the proper value if there is something in TR.TotalRequestCnt, but NULL if there is no value in the TotalRequest table for this column.
UPDATE #OutputTable
SET TotalRequestCount = ISNULL(TR.TotalRequestCnt, 0)
FROM #TotalRequest TR
JOIN #OutputTable OT
ON TR.Document = OT.Document
Values of Document are identifying INTs (5577,5575, 5574).
#TotalRequest values are all INT:
5577 NULL NULL
5575 NULL NULL
5574 2 1
I have also tried using COALESCE() instead of ISNULL() to no success.
I found the answer.
No update is being performed in the row at all because there are no values so ISNULL never has the chance to fire.
I know that in SQL when we compare two NULL values, result is always false. Hence, statements like
SELECT case when NULL = NULL then '1' else '0' end
will always print '0'. My question is how functions like ISNULL determine whether value is null or not. Because, as per my understanding (and explained in above query) comparison of two null values is always FALSE.
You need to set the set ansi_nulls off and then check your result. Null can be thought of as an unknown value and when you are comparing two unknown values then you will get the result as false only. The comparisons null = null is undefined.
set ansi_nulls off
SELECT case when NULL = NULL then '1' else '0' end
Result:-
1
From MSDN
When SET ANSI_NULLS is OFF, the Equals (=) and Not Equal To (<>)
comparison operators do not follow the ISO standard. A SELECT
statement that uses WHERE column_name = NULL returns the rows that
have null values in column_name. A SELECT statement that uses WHERE
column_name <> NULL returns the rows that have nonnull values in the
column. Also, a SELECT statement that uses WHERE column_name <>
XYZ_value returns all rows that are not XYZ_value and that are not
NULL.
As correctly pointed by Damien in comments the behavior of NULL = NULL is unknown or undefined.
Your initial assumption appears to be that ISNULL is an alias for existing functionality which can be implemented directly within SQL statements, in the same way that a SQL function can. You are then asking how that function works.
This is an incorrect starting point, hence the confusion. Instead, like similar commands such as IN and LIKE, ISNULL is parsed and run within the database engine itself; its actual implementation is most likely written in C.
If you really want to look into the details of the implementation, you could take a look instead at mySQL - it's open source, so you may be able to search through the code to see how ISNULL is implemented there. They even provide a guided tour of the code if required.
... or {2} are you literally asking how the ISNULL function in SQL
Server itself works?
Actually I am asking for the second{2}. How ISNULL function in SQL server
works. If comparison of two nulls is not defined/unknown then how
isnull function compares two null values to return appropriate
results?
Null is a special marker used in Structured Query Language (SQL) to indicate that a data value does not exist in the database. ... NULL (SQL)
ISNULL ( check_expression , replacement_value ) is not concerned with comparison of values at all. It is concerned purely with the existence of value in the first parameter.
It tests if the check_expression has any value. If it does have any value that value is returned. If check_expression has no value the ISNULL function returns the second parameter replacement_value.
It does NOT compare the two values. It tests forthe existence of value in the first parameter only.
set ansi_nulls off
SELECT case when NULL = NULL then '1' else '0' end
result=1
set ansi_nulls on
SELECT case when NULL = NULL then '1' else '0' end
result=0
so that is the difference
I hope it works
SELECT CASE WHEN ISNULL(NULL,NULL) = NULL THEN 1 ELSE 0 END
SELECT case when 'NULL' = 'NULL' then '1' else '0' end
SELECT case when isnull(columnname,'NULL')='NULL' then '1' else '0' end
SET ANSI_NULLS OFF
SELECT case when NULL = NULL then '1' else '0' end
I am not really sure what I am doing wrong, but it is Monday so this is expected. I am trying to process some data in a table. Occasionally, one of the columns will contain a question mark. I would like to replace all question marks to NULL.
This is my query, but it seems to just replace every single entry.
Update Table
set [Hours] = REPLACE([Hours], '?', NULL)
I have also tried
Update Table
set [Hours] = REPLACE([Hours], CHAR(63), NULL)
I am pretty confident I am missing the simplest mistake. I just can't see it for some reason.
I would rewrite this query to not use a REPLACE
UPDATE Table SET [Hours] = NULL WHERE [Hours] = '?'
EDIT: As for the reason your original query didn't work, as AlexK and roryap say, The docs for REPLACE say that:
Returns NULL if any one of the arguments is NULL.
You can test this by performing a simple replace, such as:
SELECT REPLACE('asdf', '?', NULL)
This will return null, even though ? isn't in the search string.
Use a where clause;
Update Table set [Hours] = NULL
where [Hours] like '%?%'
According to http://technet.microsoft.com/en-us/library/ms186862.aspx, REPLACE
Returns NULL if any one of the arguments is NULL.
Use the WHERE clause, as suggested by the other answers:
UPDATE Table SET [Hours] = NULL WHERE [Hours] = '?'
Try this instead
update table set Hours = null where Hours='?'
So I have a simple query that returns a listing of products
SELECT Model, CategoryID
FROM Products
WHERE (Model = '010-00749-01')
This returns
010-00749-01 00000000-0000-0000-0000-000000000000
010-00749-01 NULL
Which is correct, so I wanted only the products whose CategoryID is not '00000000-0000-0000-0000-000000000000' so I have
SELECT Model, CategoryID
FROM Products
WHERE (Model = '010-00749-01')
AND (CategoryID <> '00000000-0000-0000-0000-000000000000')
But this returns no result. So I changed the query to
SELECT Model, CategoryID
FROM Products
WHERE (Model = '010-00749-01')
AND ((CategoryID <> '00000000-0000-0000-0000-000000000000') OR (CategoryID IS NULL))
Which returns expected result
010-00749-01 NULL
Can someone explain this behavior to me?
MS SQL Server 2008
Check out the full reference on Books Online - by default ANSI_NULLS is on meaning you'd need to use the approach you have done. Otherwise, you could switch that setting OFF at the start of the query to switch the behaviour round.
When SET ANSI_NULLS is ON, a SELECT
statement that uses WHERE column_name
= NULL returns zero rows even if there are null values in column_name. A
SELECT statement that uses WHERE
column_name <> NULL returns zero rows
even if there are nonnull values in
column_name.
...
When SET ANSI_NULLS
is ON, all comparisons against a null
value evaluate to UNKNOWN. When SET
ANSI_NULLS is OFF, comparisons of all
data against a null value evaluate to
TRUE if the data value is NULL.
Here's a simple example to demonstrate the behaviour with regard to comparisons against NULL:
-- This will print TRUE
SET ANSI_NULLS OFF;
IF NULL <> 'A'
PRINT 'TRUE'
ELSE
PRINT 'FALSE'
-- This will print FALSE
SET ANSI_NULLS ON;
IF NULL <> 'A'
PRINT 'TRUE'
ELSE
PRINT 'FALSE'
In general, you have to remember that NULL generally means UNKNOWN. That means if you say CategoryID <> '00000000-0000-0000-0000-000000000000' you have to assume that the query will only return values that it KNOWS will meet your criteria. Since there is a NULL (UNKNOWN) result, it does not actually know if that record meets your criteria and therefore will not be returned in the dataset.
Basically, a NULL is the absence of any value. So trying to compare the NULL in CategoryId to a varchar value in the query will always result in a false evaluation.
You might want to try using the COALESCE function, something like:
SELECT ModelId, CategoryID
FROM Products
WHERE (ModelId = '010-00749-01')
AND ( COALESCE( CategoryID, '' ) <> '00000000-0000-0000-0000-000000000000' )
EDIT
As noted by AdaTheDev the COALESCE function will negate any indices that may exist on the CategoryID column, which can affect the query plan and performance.
look at this:
1=1 --true
1=0 --false
null=null --false
null=1 --false
1<>1 --false
1<>0 --true
null<>null --false
null<>1 --false <<<--why you don't get the row with: AND (CategoryID <> '00000000-0000-0000-0000-000000000000')
Null gets special treatment. You need to explicitly test for null. See http://msdn.microsoft.com/en-us/library/ms188795.aspx
You may try using the Coalesce function to set a default value for fields that have null:
SELECT Model , CategoryID
FROM Products
WHERE Model = '010-00749-01'
AND Coalesce(CategoryID,'') <> '00000000-0000-0000-0000-000000000000'
I think the problem lies in your understanding of NULL which basically means "nothing." You can't compare anything to nothing, much like you can't divide a number by 0. It's just rules of math/science.
Edit:
As Ada has pointed out, this could cause an indexed field to no longer use an index.
Solution:
You can create an index using the coalesce function: eg create index ... coalesce(field)
You can add a not null constraint to prevent NULLs from ever appearing
A de facto standard of mine is to always assign default values and never allow nulls
I am creating a stored proc that selects a value from a table and uses it in another procedure. If the first value that is searched doesn’t exist I need it to use a default value. I’m new to stored procs so I’m not sure of the best practices.
Here is the first select statement which may or may not return a value. If it doesn’t return a value I need to set the “#theValue” to 10 so that it can be used in the next select statement.
DECLARE #TheValue nvarchar(50)
SELECT #TheValue = deviceManager.SystemSettings.Value
FROM deviceManager.SystemSettings
WHERE (deviceManager.SystemSettings.Setting = 'expire-terminal-requests'
What would be the best solution?
DECLARE #TheValue nvarchar(50)
SELECT #TheValue = deviceManager.SystemSettings.Value
FROM deviceManager.SystemSettings
WHERE (deviceManager.SystemSettings.Setting = 'expire-terminal-requests'
-- Assuming #TheValue is an output parameter
SELECT #TheValue = ISNULL(#TheValue, 10)
Another possibility, set the default value before the query
DECLARE #TheValue nvarchar(50)
SET #TheValue = 'Some default Value'
SELECT #TheValue = deviceManager.SystemSettings.Value
FROM deviceManager.SystemSettings
WHERE deviceManager.SystemSettings.Setting = 'expire-terminal-requests'
This will always return either the default or the correct value.
Hope this helps.
#TheValue will be NULL if the select doesn't hit any rows. And NULL is a good value to indicate "not found".
One trick with NULLs is that you have to check for them with is null instead of = null, for example:
where #TheValue is NULL
coalesce returns the first non-null value from the list, is also ANSI standard.
SET #TheValue = coalesce (some_expresson_that_may_return_null
,some_other_expresson_that_may_return_null
,and_another_expresson_that_may_return_null
,default_value)