我有一些SQL查询具有一列可以采用NULL
的表
在下面的代码中,@term_type_id
可以是NULL
,而列term_type_id
可以有NULL
个值。
因此,如果@term_type_id
有值,则下面的代码有效,但如果@term_type_id
为NULL
,则无法使用。
设置SET ANSI_NULLS OFF
是解决问题的方法,但我知道这会在某个阶段折旧。
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]
我过去所做的就是拥有这样的东西
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
虽然这有效,但它非常冗长,使代码难以阅读和维护
有没有人有比使用SET ANSI_NULLS
OFF更好的解决方案,或者必须编写条件代码只是为了管理某些东西可能是值或NULL
的情况?
BTW - 当我使用SET ANSI_NULLS OFF时,我只针对特定查询执行此操作,然后将其重新打开。我确实理解为什么这是不赞成的原因,但这是以编写无意义的代码来绕过一个纯粹的&#39; NULL的视图。
本
答案 0 :(得分:1)
由于列和参数都可以为null,因此您应该同时处理这两种情况:
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]
请注意,这只会在列和参数都为null时返回结果,或者它们都不为null。
答案 1 :(得分:1)
Ben,if @term_type_id is NULL SELECT @term_type_id=-1
的更好解决方案
将使用isnull(@term_type_id,-1)
答案 2 :(得分:0)
试试这个,这对两种情况都有效。
SELECT ......
WHERE .....
AND ISNULL(term_type_id,-1) = ISNULL(@term_type_id,-1)
您可以使用任何静态值代替-1
或者您可以使用以下内容
SELECT ......
WHERE .....
AND ( (@term_type_id IS NULL AND term_type_id IS NULL)
OR term_type_id = @term_type_id
)
答案 3 :(得分:0)
啊 - 是的 - 谢谢你的快速反应。我想我刚刚提出了一个更好的解决方案(在这种情况下)......
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]
这适用于这种情况,因为term_type_id是身份(1,1)的结果,因此不能为-1。
答案 4 :(得分:0)
如果它是搜索条件中唯一可以为空的列,最好的方法是在单个UNION
语句中拆分条件:
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 ...
这是您可能的最快代码,主要是因为SQL Server对OR
条件没有特别的诀窍。但是,另一个可以为空的列将把它变成一个相当不愉快的混乱。
如果您认为自己可以牺牲性能,那么T-SQL中有一个非常有用的功能 - NULLIF()
:
select date, value from dbo.History
where nullif(@term_type_id, term_type_id) is null
-- Remaining search criteria
and ...
然而,这种情况很可能是非SARGable。另请注意,参数的顺序在NULLIF()
中很重要。或者,您可以设计各种复杂度的CASE
构造,这些构造可能在语义上更适合您的确切要求。