鉴于:
下面的 Select 语句:
select case NULL
when NULL then 0
else 1
end
问题:
我希望这会返回 0,但它会返回 1。什么给出了?
鉴于:
下面的 Select 语句:
select case NULL
when NULL then 0
else 1
end
问题:
我希望这会返回 0,但它会返回 1。什么给出了?
一般来说,NULL 不是您应该尝试比较是否相等的东西,这是 case 语句所做的。您可以使用“Is NULL”来测试它。没有期望那个NULL != NULL
或那个NULL = 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
问题是您的案例选择会自动尝试使用相等操作。这根本不适用于NULL。
我打算将此作为评论添加到 Aaron 的答案中,但它太长了,所以我将其添加为另一个(部分)答案。
该CASE
语句实际上有两种不同的模式,简单模式和搜索模式。
来自 BOL:
CASE 表达式有两种格式:
简单 CASE 表达式将一个表达式与一组简单表达式进行比较以确定结果。
搜索到的 CASE 表达式计算一组布尔表达式以确定结果。
当简单CASE
(您的示例)执行它所描述的比较时,它会进行相等比较- 即=
这在后面的文档中得到了澄清:
简单的 CASE 表达式通过将第一个表达式与每个 WHEN 子句中的表达式进行比较以获得等效性来进行操作。如果这些表达式等价,则返回 THEN 子句中的表达式。
- 只允许相等检查。
因为anything = NULL
在 ANSI SQL 中总是错误的(如果你不知道这一点,你需要更一般地阅读 SQL 中的 NULL,尤其是在其他搜索比较中的行为 - WHERE x IN (a, b, c)
),你不能NULL
在简单的情况下使用并且是否曾经将它与一个值进行比较,NULL
无论是在初始表达式中还是在要比较的表达式列表中。
如果要检查NULL
,则必须使用IF/ELSE
构造或CASE
带有完整表达式的搜索。
我同意不幸的是,没有支持 IS 比较以使其更易于编写的版本:
select case colname
when IS NULL then 0
else 1
end
这将使编写某些长CASE
语句更容易:
select 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
or COALESCE
:
select case COALESCE(colname, 999999) -- 999999 is some value never used
when 999999 then ''
when 1 then 'a'
when 2 then 'b'
when 3 then 'c'
when 4 then 'd'
else 'z'
end
但这并不总是一个很好的选择。
除了其他答案之外,您需要CASE
稍微更改语法来执行此操作:
SELECT CASE
WHEN NULL IS NULL THEN 0
ELSE 1
END;
在您的语法中使用该值会隐式使用等于比较。NULL
是未知的,因此也是未知的NULL = NULL
,因此使用您当前的代码,您将始终得到零1(天哪,我也这样做了)。
要获得您想要的行为,您可以使用SET ANSI_NULLS ON;但是请注意,这可能会以您可能无法预测的方式更改其他代码,并且该设置已被弃用 - 因此它将在 SQL Server 的未来版本中完全停止工作(请参阅此 SQL Server 2008 文档)。
您需要使用 IS NULL 运算符。标准比较运算符不适用于 NULL。
查看这些可能有用的关于 Null 的 MSDN 文章: