简体   繁体   中英

NULLs and SET ANSI_NULLS OFF

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM