Sql Server:与NULL比较时,CASE语句执行意外行为

时间:2011-08-31 16:42:24

标签: sql sql-server null case-statement

鉴于:

以下Select语句:

select case NULL
       when NULL then 0
       else 1
       end

问题:

我希望这会返回0但是它返回1.什么给出了?

5 个答案:

答案 0 :(得分:9)

一般来说,NULL不是你应该尝试比较相等的东西,这是case语句的作用。您可以使用“Is NULL”来测试它。没有期望NULL != NULLNULL = NULL。这是一个不确定的,未定义的值,而不是一个常数。

- 包含评论中的问题 -

如果您在遇到NULL列时需要检索值,请尝试改为:

Case
  When SomeColumn IS NULL
  Then 0
  Else 1
End

我认为应该有效。就你原来的帖子而言:

Select Case NULL
  When NULL then 0 // Checks for NULL = NULL
  else 1 // NULL = NULL is not true (technically, undefined), else happens
end

问题是您的Case select会自动尝试使用相等操作。这根本不适用于NULL。

答案 1 :(得分:4)

我打算将此添加为对Aaron答案的评论,但是它太长了,所以我将其添加为另一部分(答案的一部分)。

CASE statement实际上有两种不同的模式,简单和搜索。

来自BOL:

  

CASE表达式有两种格式:

     
      
  • 简单的CASE表达式将表达式与一组简单表达式进行比较,以确定结果。

  •   
  • 搜索到的CASE表达式计算一组布尔表达式以确定结果。

  •   

当简单的CASE(您的示例)执行其描述为比较时,它执行相等比较 - 即=

这在后面的文档中阐明:

  

简单的CASE表达式通过比较第一个表达式来运行   到每个WHEN子句中的表达式的等价性。如果这些   表达式是等价的,THEN子句中的表达式将是   返回。

     
      
  • 仅允许进行相等检查。
  •   

因为{1}在ANSI SQL中始终为false(如果您不知道这一点,则需要更一般地读取SQL中的NULL,尤其是其他搜索比较中的行为 - {{ 1}}),你不能在一个简单的情况下使用anything = NULL并将它与一个值进行比较,在初始表达式或列表中有一个WHERE x IN (a, b, c)要与之比较的表达方式。

如果您要查看NULL,则必须使用NULL构造或带有完整表达式的搜索NULL

我同意很遗憾没有支持IS比较的版本,以便更容易编写:

IF/ELSE

这样可以更轻松地编写某些长CASE语句:

select case colname
   when IS NULL then 0
   else 1
end

但那只是一厢情愿的想法......

选项是使用CASEselect case colname when IS NULL then '' when 1 then 'a' when 2 then 'b' when 3 then 'c' when 4 then 'd' else 'z' end

ISNULL

但它并不总是一个很好的选择。

答案 2 :(得分:3)

除了其他答案之外,您还需要稍微更改CASE的语法来执行此操作:

SELECT CASE 
    WHEN NULL IS NULL THEN 0
    ELSE 1
    END;

使用语法中的值隐式使用等于比较。 NULL未知,NULL = NULL也是如此,因此使用当前代码,您将始终获得 1(geez我也做过)。

要获得所需的行为,您可以使用SET ANSI_NULLS ON;但请注意,这可能会以您可能无法预测的方式更改其他代码,并且该设置已弃用 - 因此它将在SQL Server的未来版本中停止工作(请参阅this SQL Server 2008 doc)。

答案 3 :(得分:0)

您需要使用IS NULL运算符。标准比较运算符不适用于NULL。

答案 4 :(得分:0)

查看这些可能有用的关于Null的MSDN文章: