I have a bit of SQL that queries a table that has one column that can take NULL
.
In the code below the @term_type_id
could be NULL
, and the column term_type_id
could have NULL
values.
So the code below works if @term_type_id
has a value, but does not work if @term_type_id
is NULL
.
Setting SET ANSI_NULLS OFF
is a way around the problem, but I do know that this will be depreciated at some stage.
SELECT [date],value FROM history
WHERE id=@id
AND data_type_id=@data_type_id
AND quote_type_id=@quote_type_id
AND update_type_id=@update_type_id
AND term_type_id=@term_type_id
AND source_id=@source_id
AND ([date]>=@temp_from_date and [date]<=@temp_to_date)
ORDER BY [date]
What I have done in the past is to have something like this
if @term_type_id is NULL
BEGIN
SELECT ......
WHERE .....
AND term_type_id IS NULL
END
BEGIN
SELECT ......
WHERE .....
AND term_type_id = @term_type_id
END
While this works, it is very verbose and makes the code hard to read and maintain.
Does anyone have a better solution than using SET ANSI_NULLS
OFF or having to write conditional code just to manage the case when something could be a value or NULL
?
BTW - When I use SET ANSI_NULLS OFF, I only do it for the specific query then turn it back on afterwards. I do understand the reasons why this is frowned upon, but it is at the expense of writing pointless code to get around a 'pure' view of NULL.
Ben
Since both the column and the parameter can be null, you should treat both cases:
SELECT [date],value FROM history
WHERE id=@id
AND data_type_id=@data_type_id
AND quote_type_id=@quote_type_id
AND update_type_id=@update_type_id
AND ((term_type_id IS NULL AND @term_type_id IS NULL) OR term_type_id = @term_type_id)
AND source_id=@source_id
AND ([date]>=@temp_from_date and [date]<=@temp_to_date)
ORDER BY [date]
Note that this will only return results when both column and parameter are null, or none of them is null.
Ben, if @term_type_id is NULL SELECT @term_type_id=-1
,则更好的解决方案if @term_type_id is NULL SELECT @term_type_id=-1
使用isnull(@term_type_id,-1)
Try this, this will work on both case.
SELECT ......
WHERE .....
AND ISNULL(term_type_id,-1) = ISNULL(@term_type_id,-1)
You can use any static value instead of -1
Or you can use something like below
SELECT ......
WHERE .....
AND ( (@term_type_id IS NULL AND term_type_id IS NULL)
OR term_type_id = @term_type_id
)
Ahh - yes - thank you for the prompt responses. I think I have just come up with a better solution (well in this case)...
if @term_type_id is NULL SELECT @term_type_id=-1
SELECT [date],value FROM history
WHERE id=@id
AND data_type_id=@data_type_id
AND quote_type_id=@quote_type_id
AND update_type_id=@update_type_id
AND ISNULL(term_type_id,-1)=@term_type_id
AND source_id=@source_id
AND ([date]>=@temp_from_date and [date]<=@temp_to_date)
ORDER BY [date]
This works in this case as term_type_id is the result of an identity (1,1) and thus can not be -1.
If it's the only nullable column among your search criteria, the best way would be to split conditions within a single UNION
statement:
select date, value from dbo.History
where term_type_id is null
-- Remaining search criteria
and ...
union all
select date, value from dbo.History
where term_type_id = @term_type_id
-- Remaining search criteria
and ...
This is the fastest code possible in your case, basically because SQL Server doesn't have a particular knack for OR
-ed conditions. However, another nullable column will turn this into a rather unpleasant mess.
If you think you can sacrifice performance, there is a useful function in T-SQL that does exactly that - NULLIF()
:
select date, value from dbo.History
where nullif(@term_type_id, term_type_id) is null
-- Remaining search criteria
and ...
However, this type of condition will be non-SARGable, most likely. Also, note that the order of arguments does matter in NULLIF()
. Alternatively, you can devise CASE
constructs of various complexity that might be semantically more suitable to your exact requirements.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.