使用ISNULL vs使用COALESCE检查特定条件?

JBo*_*one 71 sql t-sql coalesce isnull

我知道可以传递多个参数COALESCE,但是当你想只检查一个表达式以查看它是否存在时,你是使用默认值还是使用它更好的做法ISNULL

这两者之间是否有任何性能提升?

one*_*hen 56

Microsoft Connect上报告的此问题显示COALESCE和之间存在一些差异ISNULL:

我们处理的早期部分重写COALESCE( expression1, expression2 )CASE WHEN expression1 IS NOT NULL THEN expression1 ELSE expression2 END.在[这个例子]中:

COALESCE ( ( SELECT Nullable
             FROM Demo
             WHERE SomeCol = 1 ), 1 )
Run Code Online (Sandbox Code Playgroud)

我们生成:

SELECT CASE
          WHEN (SELECT Nullable FROM Demo WHERE SomeCol = 1) IS NOT NULL
          THEN (SELECT Nullable FROM Demo WHERE SomeCol = 1)
          ELSE 1
       END
Run Code Online (Sandbox Code Playgroud)

查询处理的后续阶段不理解这两个子查询最初是同一个表达式,因此它们执行子查询两次...

一种解决方法虽然我讨厌建议,但是要COALESCE改为ISNULL,因为后者不会复制子查询.

  • 快速问题,如果你有3个值,比如coalesce(expression1,expression2,expression3,1),那些'表达式'实际上是select语句,它会对实际的嵌套isnull语句有意义吗?即isnull(expression1,isnull(expression2,isnull(expression3,1))) (2认同)

Gol*_*rol 24

我认为不是,但COALESCE符合SQL '92标准,并受更多不同数据库的支持.如果你想要便携性,不要使用ISNULL.

  • 我完全赞同.; -D它是Oracle中的NVL. (9认同)
  • ifnull是无效的吗? (2认同)

小智 11

COALESCE中,您可以拥有多个表达式,而在ISNULL中,您只能检查一个表达式

COALESCE ( expression [ ,...n ] ) 

ISNULL ( check_expression , replacement_value )
Run Code Online (Sandbox Code Playgroud)


cro*_*sek 7

值得一提的是,两者之间的类型处理也会有所不同(参见相关答案项目(2)).

假设查询尝试使用快捷方式来编写空比较:

select * from SomeTable
 where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);
Run Code Online (Sandbox Code Playgroud)

这与...不同

select * from SomeTable
 where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);
Run Code Online (Sandbox Code Playgroud)

因为在第一种情况下,IsNull()强制类型为一位(因此-1转换为true),而第二种情况将两者都提升为int.

with input as 
(
  select convert(bit, 1) as BitOn,      
         convert(bit, 0) as BitOff,
         convert(bit, null) as BitNull
)
select BitOn, 
       BitOff,
       BitNull,
       IsNull(BitOn, -1) IsNullBitOn,         -- true
       IsNull(BitOff, -1) IsNullBitOff,       -- false
       IsNull(BitNull, -1) IsNullBitNull,     -- true, converts the -1 to bit
       coalesce(BitOn, -1) CoalesceBitOn,     -- 1
       coalesce(BitOff, -1) CoalesceBitOff,   -- 0       
       coalesce(BitNull, -1) CoalesceBitNull  -- -1
  from input;
Run Code Online (Sandbox Code Playgroud)

关于问题本身也有类似的评论/链接(@Martin Smith).


got*_*tqn 6

NULLCOALESCE并不总是可互换。应该了解它们的差异,以便知道何时使用一个比另一个更好:

在此处输入图片说明

上表为之间的比较ISNULL,并COALESCEExam Ref 70-761 Querying Data with Transact-SQL由伊茨克奔甘写的书。


  1. 支持的参数数量 - 2for ISNULLvs>2使用时COALESCE
  2. ISNULL是专有的 T-SQL 功能,COALESCE是 ISO/ANSI SQL 标准
  3. 结果的数据类型很重要。阅读上表中的注释后,请检查以下情况:

    DECLARE @x VARCHAR(3)  = NULL
           ,@y VARCHAR(10) = '1234567890';
    
    SELECT ISNULL(@x, @y) AS [ISNULL], COALESCE(@x, @y) AS [COALESCE];
    
    Run Code Online (Sandbox Code Playgroud)

    在此处输入图片说明

    ISNULL越来越的第一个参数的数据类型,因为它是不 NULL字面。它是VARCHAR(3)和是结果,第二个参数数据被剪切以匹配它。随着COALESCE数据类型,如果使用最高优先级。

    DECLARE @x VARCHAR(8)  = '123x5'
           ,@y INT = 123;
    
    SELECT ISNULL(@x, @y) AS [ISNULL];
    SELECT COALESCE(@x, @y) AS [COALESCE];
    
    Run Code Online (Sandbox Code Playgroud)

    在此处输入图片说明

    在此处输入图片说明

    ISNULL将返回第一个参数的数据类型,而 COALESCE我们得到的错误,因为INT具有最高的优先级,并第一个参数值的转换INT失败。

  4. 结果的可空性也很重要。例如:

    DECLARE @x VARCHAR(3) = NULL
           ,@y VARCHAR(3) = NULL;
    
    DROP TABLE IF EXISTS [dbo].[DataSource01];
    
    SELECT ISNULL(10, 20) AS [C1]
          ,ISNULL(@x, 'text') AS [C2]
          ,ISNULL(@x, @y) AS [C3]
    INTO [dbo].[DataSource01];
    
    DROP TABLE IF EXISTS [dbo].[DataSource02];
    
    SELECT COALESCE(10, 20) AS [C1]
          ,COALESCE(@x, 'text') AS [C2]
          ,COALESCE(@x, @y) AS [C3]
    INTO [dbo].[DataSource02];
    
    Run Code Online (Sandbox Code Playgroud)

    让我们检查Nullable每一列的属性:

    在此处输入图片说明

    在此处输入图片说明

    使用COALESCE我们将NOT NULLcolumn的属性设置为Yes,仅当所有输入都不能为空时。

  5. 根据 SQL 标准,COALESCE表达式被翻译为:

    CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
    
    Run Code Online (Sandbox Code Playgroud)

    如果 WHEN 子句中子查询的执行结果不为 NULL,SQL Server 将在 THEN 子句中再次执行它。换句话说,在这种情况下,它会执行两次。只有当 WHEN 子句中的执行结果为 NULL 时,SQL Server 才不会再次执行子查询,而是返回 ELSE 表达式。所以在使用子查询时,ISNULL 函数具有性能优势。


BIC*_*ube 5

我没有看到明确指出的一个主要问题是ISNULL的输出类型类似于第一个表达式,但是COALESCE它返回的是优先级最高的值的数据类型。

DECLARE @X VARCHAR(3) = NULL
DECLARE @Y VARCHAR(10) = '123456789'
/* The datatype returned is similar to X, or the first expression*/
SELECT ISNULL(@X, @Y) ---> Output is '123'
/* The datatype returned is similar to Y, or to the value of highest precedence*/
SELECT COALESCE(@X, @Y) ---> Output is '123456789'
Run Code Online (Sandbox Code Playgroud)

  • 这与第一和第二/第N个表达式无关。参见[here](http://stackoverflow.com/questions/18828641/sql-difference-between-coalesce-and-isnull/18828687#18828687):`ISNULL使用第一个参数的数据类型,COALESCE遵循CASE表达式规则并返回优先级最高的value的数据类型。 (3认同)