没有 ISNULL 的条件是不是很臭?
Are conditions without ISNULL stinky?
我看到一篇描述 SQL 代码可能不正确的不同情况的文章。然而,有一个 point 让我感到惊讶。他们声称
it is wise to explicitly handle NULLs in nullable columns, by using COALESCE to provide a default value
ISNULL
也被提及。他们还引用了 MSDN web page 给出了 ISNULL
的示例。这里的基本思想是最好使用
SELECT COUNT(*) FROM [dbo].[Table1] WHERE ISNULL([c2],0) > 2;
然后
SELECT COUNT(*) FROM [dbo].[Table1] WHERE [c2] > 2;
然而,第一个变体不会是 SARG,而结果完全不受 ISNULL
的影响。我理解需要在输出中使用 ISNULL
或 COALESCE
来处理 NULL
,但是,我总是尝试使用 IS NULL
或 IS 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?
您提供的示例中的 isnull
检查毫无意义。 null > 2
returns null
,这不是 "true",因此这些行无论如何都会从查询中排除。要启动,以这种方式使用 isnull
将禁止优化器使用 c2
上的索引(如果有的话)。
简而言之 - 这听起来像是糟糕的建议。
我看到一篇描述 SQL 代码可能不正确的不同情况的文章。然而,有一个 point 让我感到惊讶。他们声称
it is wise to explicitly handle NULLs in nullable columns, by using COALESCE to provide a default value
ISNULL
也被提及。他们还引用了 MSDN web page 给出了 ISNULL
的示例。这里的基本思想是最好使用
SELECT COUNT(*) FROM [dbo].[Table1] WHERE ISNULL([c2],0) > 2;
然后
SELECT COUNT(*) FROM [dbo].[Table1] WHERE [c2] > 2;
然而,第一个变体不会是 SARG,而结果完全不受 ISNULL
的影响。我理解需要在输出中使用 ISNULL
或 COALESCE
来处理 NULL
,但是,我总是尝试使用 IS NULL
或 IS 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?
您提供的示例中的 isnull
检查毫无意义。 null > 2
returns null
,这不是 "true",因此这些行无论如何都会从查询中排除。要启动,以这种方式使用 isnull
将禁止优化器使用 c2
上的索引(如果有的话)。
简而言之 - 这听起来像是糟糕的建议。