Sql Server:CASE 语句与 NULL 比较时出现意外行为
给定:
以下 Select 语句:
select case NULL
when NULL then 0
else 1
end
问题:
我期望它返回 0,但它却返回 1。结果是什么?
Given:
The following Select statement:
select case NULL
when NULL then 0
else 1
end
Problem:
I'm expecting this to return 0 but instead it returns 1. What gives?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
一般来说,您不应该尝试比较 NULL 是否相等,而 case 语句就是这样做的。您可以使用“Is NULL”来测试它。不存在
NULL != NULL
或NULL = NULL
的期望。它是一个不确定的、未定义的值,而不是一个硬常量。-- 为了包含评论中的问题 --
如果您需要在可能遇到 NULL 列时检索值,请尝试这样做:
我相信这应该可行。就您的原始帖子而言:
问题是您的案例选择会自动尝试使用相等操作。这对于 NULL 来说根本不起作用。
Generally speaking, NULL is not something you should attempt to compare for equality, which is what a case statement does. You can use "Is NULL" to test for it. There is no expectation that
NULL != NULL
or thatNULL = NULL
. It's an indeterminate, undefined value, not a hard constant.-- To encompass questions in the comments --
If you need to retrieve a value when you may encounter a NULL column, try this instead:
I believe that should work. As far as your original post is concerned:
The trouble is that your Case select automatically attempts to use equality operations. That simply doesn't work with NULL.
我本来打算将其添加为亚伦答案的评论,但它太长了,所以我将其添加为另一个(部分)答案。
CASE
语句实际上有两种不同的模式,简单,搜索。来自博尔:
当简单的
CASE
(您的示例)执行其所描述的比较时,它会执行相等比较 - 即=
这在后面的文档中得到了澄清:
因为
anything = NULL
在 ANSI SQL 中始终为 false(如果您不知道这一点,则需要更广泛地阅读 SQL 中的 NULL,特别是其他搜索比较中的行为 -WHERE x IN (a, b, c)
),您不能在简单情况下使用NULL
并将其与值进行比较,带有NULL
要么初始表达式或要比较的表达式列表中的值。如果要检查
NULL
,则必须使用IF/ELSE
构造或带有完整表达式的搜索CASE
。我同意,不幸的是没有版本支持 IS 比较以使其更容易编写:
这将使编写某些长
CASE
语句更容易:但这只是一厢情愿的想法......
一个选项是使用
ISNULL
或COALESCE
:但这并不总是一个好的选择。
I was going to add this as a comment to Aaron's answer, but it was getting too long, so I'll add it as another (part of the) answer.
The
CASE
statement actually has two distinct modes, simple and searched.From BOL:
When the simple
CASE
(your example) does what it describes as comparison it does an equality comparison - i.e.=
This is clarified in the later documentation:
Because
anything = NULL
is always false in ANSI SQL (and if you didn't know this, you need to read up on NULLs in SQL more generally, particularly also with the behavior in the other searched comparison -WHERE x IN (a, b, c)
), you cannot useNULL
in a simple case and have it ever be compared to a value, with aNULL
either in the initial expression or in the list of expressions to be compared against.If you want to check for
NULL
, you will have to use anIF/ELSE
construct or the searchedCASE
with a full expression.I agree that it's kind of unfortunate there is no version which supports an IS comparison to make it easier to write:
Which would make writing certain long
CASE
statements easier:But that's just wishful thinking...
An option is to use
ISNULL
orCOALESCE
:But it isn't always a great option.
除了其他答案之外,您还需要稍微更改
CASE
的语法才能执行此操作:在语法中使用值隐式使用 equals 比较。
NULL
是未知的,NULL = NULL
也是未知的,因此使用您当前的代码,您将始终得到zero1(天哪,我也这样做了) 。要获得所需的行为,可以使用 SET ANSI_NULLS ON ;但请注意,这可能会以您可能无法预测的方式更改其他代码,并且该设置已被弃用 - 因此它将在 SQL Server 的未来版本中完全停止工作(请参阅 此 SQL Server 2008 文档)。
In addition to the other answers, you need to change the syntax for
CASE
slightly to do this:Using the value in your syntax implicitly uses an equals comparison.
NULL
is unknown, and so isNULL = NULL
, so with your current code you will always getzero1 (geez I did it too).To get the behavior you want, you can use SET ANSI_NULLS ON; however note that this can change other code in ways you may not be able to predict, and the setting is deprecated - so it will stop working at all in a future version of SQL Server (see this SQL Server 2008 doc).
您需要使用 IS NULL 运算符。标准比较运算符不适用于 NULL。
You need to use the IS NULL operator. Standard comparison operators do not work with NULL.
查看这些可能有用的有关 Null 的 MSDN 文章:
Check out these MSDN articles about Null that may be useful: