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


74

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

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


5
COALESCE文档有这样一个字条:ISNULL和COALESCE虽然等同,可以表现不同。包含具有非空参数的ISNULL的表达式被视为NOT NULL,而包含具有非空参数的COALESCE的表达式被视为NULL ...

3
ISNULL还将结果强制为第一个表达式的数据类型,如下所示
Martin Smith

4
本文很好地阐明了这些差异。sqlmag.com/t
Data

这是一个很好的文章,以及... mssqltips.com/sqlservertip/2689/...
goodeye

Answers:


58

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

查询处理的后期阶段不了解这两个子查询原本是相同的表达式,因此它们执行了两次子查询...

尽管我不愿提出建议,但一种解决方法是将更COALESCE改为ISNULL,因为后者不会复制子查询。


2
一个简单的问题,如果您有3个值,例如coalesce(expression1,expression2,expression3、1),这些“表达式”实际上是select语句,那么对嵌套的isull语句进行实际处理有意义吗?即isull(expression1,isull(expression2,isull(expression3,1)))
ganders 2015年

25

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


@AaronAnodide MySQL使用ifnullsql server isnull
nawfal

12

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

COALESCE ( expression [ ,...n ] ) 

ISNULL ( check_expression , replacement_value )

8

值得一提的是,两者之间的类型处理也可以有所作为(请参阅此相关答案项(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)。


7

我没有看到明确指出的一个主要问题是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'

3
这与第一和第二/第N个表达式无关。看到这里ISNULL uses the data type of the first parameter, COALESCE follows the CASE expression rules and returns the data type of value with the highest precedence.
underscore_d

5

NULLCOALESCE并不总是可互换。它应该知道它们之间的差异,以便知道何时更好地使用它们:

在此处输入图片说明

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


  1. 支持的参数的数量-2ISNULLVS>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将column的属性设置为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函数具有性能优势。


2

如果只有一个空条件,ISNULL则开销会更少。但是,差异可能微不足道。


1
您是否支持开销少的说法有任何支持ISNULL吗?
约书亚德雷克2014年

1
@JoshuaDrake:有两个区域COALESCE可以互换使用,因此会带来更多开销。首先,ISNULL处理固定数量的输入,其中COALESCE指定用于任何数量的输入。其次,COALESCE配置为返回具有最高数据类型优先级的表达式的数据类型,而ISNULL返回与相同的类型check_expression。就像我上面说的,在更高版本的SQL Server中,差异可能可以忽略不计,但严格来说,仍然存在开销。
James Johnson

2

这个解释清楚地说明了合并与非空

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

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

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/


-2

在COALESCE中,可以使用多个表达式,它将返回不为null且首先出现的值。例如

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中,如果expression null,它将返回提供的第二个参数,当然,您只能检查一个表达式...

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


2
OP表示他们知道COALESCE处理多个参数的能力,问题在于只有两个时的特定情况。
约书亚·德雷克2014年

@JoshuaDrake请阅读完整的答案...我阅读了问题,请您完全阅读了我的答案...它很容易被
忽略,并被
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.