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.
Related
I'm passing a parameter like '1,2,3' to this statement:
SELECT *
FROM Negative
WHERE IdNegative IN (#IdNegative)
But I want to return all records (like the records with an id 1,2,3,4,5,6...) when the parameter is empty. Is there a way to do this?
Thank you.
Parameters and variables are not simply pasted into the query by the compiler. They are inserted as actual compiled values, so in this case the string 1,2,3 is never going to be equal to any of the numbers 1 2 3.
You need to declare as a table variable or as a Table-Valued Parameter
DECLARE #IdNegative TABLE (id int PRIMARY KEY);
INSERT #IdNegative VALUES (1),(2),(3);
SELECT *
FROM Negative
WHERE IdNegative IN (SELECT id FROM #IdNegative);
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.
Here is the scenario. We have a column of type IMAGE in a table that holds compressed data. This column can be null. In a different version, we moved this data to a separate table, still an image column.
We have a stored procedure that is checking where the data is, in the original table or the new table. To do that, it selects the value into a VARBINARY(MAX) variable, checks if it is null, if so grabs it from the new table.
Something strange is going on with the checks. For a few rows in the database, the column displays as NULL, but when cast to VARBINARY(MAX) it ends up being an empty value of 0x. This is only for 4 rows out of 426, all others evaluate to NULL fine. If you check for null in the table itself, like WHERE <column> IS NULL it evalulates to true, but if you do WHERE CAST(<column> as VARBINARY(MAX)) IS NULL it evaluates to false.
I can change around my stored procedure so that it handles correctly, but I'm a little baffled as to what is going on here. Any ideas?
This is on SQL Server 2005.
***edit to try and include a clearer example
e.g.
SELECT a
FROM Table
WHERE a IS NULL
SELECT a
FROM Table
WHERE CAST(a as VARBINARY(MAX)) IS NULL
the first query returns the result with NULL, the second query doesn't return anything.
Similarily, the stored procedure looks something like this:
DECLARE #CompressedData VARBINARY(MAX)
SELECT #CompressedData = imageColumn
FROM originalTable
WHERE ID = #ID
IF (#CompressedData IS NULL)
BEGIN
SELECT #CompressedData = imageColumn
FROM newTable
WHERE ID = #ID
END
In that case, #CompressedData does not evaluate to NULL since it is getting a value of 0x
I'm using C# to write to a SQL Compact Edition 3.5 database. I got a table containing e-mail addresses and names for each address.
MailRecipientAddressID int primary key identity(1,1) not null,
Address nvarchar(4000),
Name nvarchar(4000)
In this table I want every address-name combination to be unique. In some cases it's possible that either Address or Name is NULL in a row. Before inserting new rows into this table, I'm using a SELECT query to check if there is an existing row matching the one I want to insert. When using this query
SELECT MailRecipientAddressID FROM MailRecipientAddress WHERE Address = #Address AND Name = #Name
I will not find existing rows with NULL values in one column (see here).
Now I got this query, which works and kind of solves my problem
SELECT MailRecipientAddressID FROM MailRecipientAddress WHERE ISNULL(Address, '') = ISNULL(#Address, '') AND ISNULL(Name, '') = ISNULL(#Name, '')
but even though it is no problem in my case that NULL and empty string values are handled equally, I do not like this solution. I think it's kind of hackish. Is there a better approach
to apply a filter on a SELECT statement with parameters which can contain NULL
which works on SQL CE
Edit
I do not understand why, but my query works with SQL Management Studio but it does not in my application (see here). To correct my own approach I would need to use COALESCE.
I don't like the option to replace my NULL values with empty strings because I think it would be kind of inconsequent to set a value at a place where I got no value or is my understanding of this design question wrong?
The best solution is a constraint on the table that prevents duplicates from going into the table. You can put one in with a unique index:
create unique index idx_MailRecipientAddress_address_name on MailRecipientAddress(Address, Name);
This will generate an error on the insert, which you would then need to catch.
However, this is only a partial solution, because NULL values do not count as duplicates. You might solve your overall problem by not allowing NULL values in the field at all. Instead, represent no data using empty strings. Note: I wouldn't normally recommend this. In SQL, NULL means "unknown" and by the definition of the language, two "unknown" values are not equal. However, you seem to want them to be equal.
As for SQL, yours is okay, but it equates NULL and the empty string. An explicit check is more accurate:
WHERE (Address = #Address or Address is null and #Address is null) and
(Name = #Name or Name is null and #Name is null)
#George
if Parameter value is Null and column value is not null then "(Address = #Address or Address is NULL) returns false "
if Parameter value is Null and column value is null then "(Address = #Address or Address is NULL) returns true"
if Parameter value is Not Null and column value is null then "(Address = #Address or Address is NULL) returns true"
if Parameter value is Not Null and column value is Not null and if matches then "(Address = #Address or Address is NULL) returns true otherwise false"
SELECT MailRecipientAddressID FROM MailRecipientAddress WHERE (Address = #Address or Address is NULL) AND (Name = #Name or Name is NULL)
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