2017-10-04 44 views
5

我遇到一篇描述SQL代码可能不正确的不同情况的文章。然而,有一个point这是令我惊讶的。他们声称没有ISNULL臭的条件吗?

明智的做法是明确的处理在空列空值,通过使用COALESCE提供一个默认值

ISNULL被提及为好。他们还引用这个MSDN web page举例ISNULL。这里的基本想法是,它是更好地使用

SELECT COUNT(*) FROM [dbo].[Table1] WHERE ISNULL([c2],0) > 2; 

然后

SELECT COUNT(*) FROM [dbo].[Table1] WHERE [c2] > 2; 

然而,第一变异不会是特区政府,而,结果不被ISNULL任何影响。我知道需要在输出中使用ISNULLCOALESCE来处理NULL,但是,我始终尝试使用IS NULLIS NOT NULL来处理谓词中的NULL。我想念什么? MSDN问题的重点是什么?

编辑:以上讨论反应并主要是对本post我已经准备了一个简单的测试

IF OBJECT_ID('dbo.LogTable', 'U') IS NOT NULL DROP TABLE dbo.LogTable 

SELECT TOP 100000 DATEADD(day, (ABS(CHECKSUM(NEWID())) % 65530), 0) datesent , 
     CASE WHEN (ABS(CHECKSUM(NEWID())) % 100) = 1 THEN NULL ELSE (ABS(CHECKSUM(NEWID())) % 1000) END ivalue 
INTO [LogTable] 
FROM sys.sysobjects 
CROSS JOIN sys.all_columns 

CREATE INDEX ix_logtable_ivalue ON LogTable(ivalue asc) INCLUDE(datesent); 

-- Q1 
select * from logtable where isnull(ivalue, 0) > 998 

-- Q2 
select * from logtable where ivalue > 998 

然而,在Q1的ivalue不SARG。有没有发现?我应该如何为这个特定的数据和查询创建属性SARG?

+4

你是对的。不要放入不必要的NULL检查,因为这会妨碍索引的使用。我强烈推荐'IS NULL' /'IS NOT NULL'。这些是ANSI标准结构。 –

+9

这个例子来自于旨在检测不良数据库代码以进行改进的事实,这一事实非常令人担忧。你*需要考虑当比较可能为'NULL'的值时会发生什么情况,但反思性地将'ISNULL'放在每个地方都是完全错误的。 –

+0

'MSDN问题'的一点是什么?不知道:-)来自[原始来源]的评论(https://www.red-gate.com/simple-talk/sql/t-sql-programming/sql-code-smells/#not-handling-null- values-in-nullable-columns)在计算事物时很有意义,但是[MSDN](https://msdn.microsoft.com/en-us/library/dd172133(v = vs.100).aspx)是完全错误的。 –

回答

6

isnull检查您提供的示例是毫无意义的。 null > 2返回null,这不是“真”,因此这些行将被排除在查询之外。要启动,以这种方式使用isnull将禁止优化器使用c2上的索引(如果有的话)。

总之 - 这听起来像可怜的建议。

+1

“null> 2返回null” - 不行,此比较返回未知。有点迂腐,但空洞混乱。这一点仍然是正确的 - 没有理由检查null。 – SMor

+1

@SMor:非常迂腐,因为布尔数据类型仅在T-SQL中存在。如果它真的存在(我希望它会非常有用),那么'UNKNOWN'结果几乎肯定会由'NULL'表示。不过,我不确定'NULL'如何比'UNKNOWN'更“令人困惑”,因为这首先是因为它的存在。 –

+0

'以这种方式使用isnull将禁止优化器使用c2上的索引,如果你有''不完全正确,因为可能仍然会发布'索引扫描',正如[Pankaj Manek明亮地显示我们在这里](http:///www.sqlservercentral.com/blogs/sqlyse-with-pankaj-manek/2015/08/20/isnull-around-the-predicate-and-sargability/)。该声明适用于'index seek'。 –