77

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

两者之间有性能提升吗?

4

9 回答 9

61

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 )

我们生成:

SELECT CASE
          WHEN (SELECT Nullable FROM Demo WHERE SomeCol = 1) IS NOT NULL
          THEN (SELECT Nullable FROM Demo WHERE SomeCol = 1)
          ELSE 1
       END

后面的查询处理不明白这两个子查询本来就是同一个表达式,所以执行了两次子查询……

一种解决方法,虽然我不想建议,但更改COALESCEISNULL,因为后者不复制子查询。

于 2012-02-29T10:02:17.917 回答
27

我认为不是,但 COALESCE 符合 SQL '92 标准,并受到更多不同数据库的支持。如果您追求可移植性,请不要使用 ISNULL。

于 2011-09-13T21:42:41.660 回答
13

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

COALESCE ( expression [ ,...n ] ) 

ISNULL ( check_expression , replacement_value )
于 2014-03-13T16:21:17.590 回答
9

值得一提的是,两者之间的类型处理也可以有所作为(参见这个相关的答案项 (2))。

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

select * from SomeTable
 where IsNull(SomeNullableBitField, -1) != IsNull(SomeOtherNullableBitField, -1);

这不同于

select * from SomeTable
 where coalesce(SomeNullableBitField, -1) != coalesce(SomeOtherNullableBitField, -1);

因为在第一种情况下, 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;

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

于 2014-10-06T20:45:18.073 回答
8

我没有看到明确指出的一个主要事情是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'
于 2015-06-10T02:30:00.980 回答
7

NULL并不COALESCE总是可以互换的。它应该知道它们的差异,以便知道什么时候使用一个比另一个更好:

在此处输入图像描述

上表是Itzik Ben-Gan 所写书籍之间ISNULLCOALESCE比较。Exam Ref 70-761 Querying Data with Transact-SQL


  1. 支持的参数数量 -2用于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];
    

    在此处输入图像描述

    正在获取第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];
    

    在此处输入图像描述

    在此处输入图像描述

    正在返回第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];
    

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

    在此处输入图像描述

    在此处输入图像描述

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

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

    CASE WHEN (<subquery>) IS NOT NULL THEN (<subquery>) ELSE 0 END
    

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

于 2017-10-05T06:59:10.093 回答
3

这个解释清楚地说明了 coalesce 与 isnull

SQL 中的 COALESCE 函数返回其参数中的第一个非 NULL 表达式。COALESCE 的语法如下:

 COALESCE ("expression 1", "expressions 2", ...)

它与以下 CASE 语句相同:

SELECT CASE ("column_name")
  WHEN "expression 1 is not NULL" THEN "expression 1"
  WHEN "expression 2 is not NULL" THEN "expression 2"
  ...
  [ELSE "NULL"]
  END
FROM "table_name";

在 SQL Server 中,ISNULL( ) 函数用于将 NULL 值替换为另一个值。

select CountryName = ISNULL("columnname", 'INDIA') from Countries

合并返回第一个非空表达式,其中 isnull() 用于将空值替换为我们想要的值。

COALESCE 是 ANSI 标准的一部分,几乎在所有数据库中都可用。

在 ISNULL v COALESCE 之间进行决定时,必须注意以下参数:

  1. COALESCE 根据数据类型优先级确定输出的类型,其中与 ISNULL 一样,数据类型不受数据类型优先级的影响。
  2. 考虑以下 sql 语句

    DECLARE @c5 VARCHAR(5);
    SELECT 'COALESCE', COALESCE(@c5, 'longer name')
    UNION ALL
    SELECT 'ISNULL',   ISNULL(@c5,   'longer name');
    

结果:

COALESCE longer name
ISNULL   longe

发生这种情况是因为 ISNULL 采用第一个参数的数据类型,而 COALESCE 检查所有元素并选择最合适的(在本例中为 VARCHAR(11))

有关在 COALESCE 与 ISNULL 之间做出决定的更详细说明,请查看: https ://www.mssqltips.com/sqlservertip/2689/deciding-between-coalesce-and-isnull-in-sql-server/

于 2017-05-27T13:47:59.750 回答
2

在只有一个空条件的情况下,ISNULL开销会更少。不过,差异可能可以忽略不计。

于 2011-09-13T21:53:51.130 回答
-2

在 COALESCE 中可以使用多个表达式,它将返回非空值并首先出现......例如

DECLARE @Value1 INT, @Value2 INT, @Value3 INT, @Value4 INT
SELECT @Value2 = 2, @Value4 = 4
SELECT COALESCE(@Value1, @Value2, @Value3, @Value4)
SELECT COALESCE(@Value1, @Value4, @Value3, @Value2)

在 ISNULL 中,如果表达式为 null,它将返回提供的第二个参数,当然您只能检查一个表达式...

因此,如果要检查多个表达式并首先选择其中不为空的,则使用合并,否则请使用 ISNULL

于 2014-04-16T12:05:45.817 回答