空结果集和 Case When = 1

Jel*_*ves 2 sql-server case

我很确定这是一个隐式转换,但我无法找到有关它的信息。

假设我有这个 SQL:

SELECT
CASE WHEN (SELECT 1 WHERE (1=1)) = 1 THEN 1 ELSE 0 END
Run Code Online (Sandbox Code Playgroud)

我的子查询返回一行,因此与 1 进行比较。这导致我的 CASE WHEN 产生 1 输出。

即使我将子查询设置为不返回如下示例所示的行,CASE 语句也会返回 0 结果:

SELECT
CASE WHEN (SELECT 1 WHERE (1=0)) = 1 THEN 1 ELSE 0 END
Run Code Online (Sandbox Code Playgroud)
  • SQL 解释器是否在“空集”到 0 或 1 之间进行转换?
  • 使用这种类型的比较让我感到不舒服。以我的拙见,最好像这样使用 EXISTS:

    SELECT
    CASE WHEN EXISTS(SELECT 1 WHERE (1=1)) THEN 1 ELSE 0 END
    
    Run Code Online (Sandbox Code Playgroud)

如果我不使用 EXISTS 有什么优点或缺点吗?

Tom*_*m V 10

SQL 解释器是否在“空集”到 0 或 1 之间进行转换?

不,查询没有返回 0,因为空结果被认为等于 0,但因为空结果集被考虑,NULL而 null 不等于任何东西。

正如你发现的

SELECT
CASE WHEN (SELECT 1 WHERE (1=0)) = 1 THEN 1 ELSE 0 END
Run Code Online (Sandbox Code Playgroud)

返回 0

SELECT
CASE WHEN (SELECT 1 WHERE (1=0)) = 0 THEN 1 ELSE 0 END
Run Code Online (Sandbox Code Playgroud)

也返回 0。

所以空结果集不是 1 也不是 0,它是 NULL,正如

SELECT
CASE WHEN (SELECT 1 WHERE (1=0)) is NULL THEN 1 ELSE 0 END
Run Code Online (Sandbox Code Playgroud)

返回 1。

使用该代码查看此dbfiddle

NULL 是未知的,所以 SQL Server 不知道它等于什么。

以我的拙见,最好使用 EXISTS

如果你依赖结果集的存在,我同意EXISTS可能是要走的路。这就是建造的目的。
如果你想比较 2 个值,你需要使用CASE但对于你陈述的场景,我会使用 EXISTS

如果您的结果集有多于一行或多列,您的比较就会中断。

例如

SELECT
CASE WHEN (SELECT 1,2 WHERE (1=1)) = 1 THEN 1 ELSE 0 END
Run Code Online (Sandbox Code Playgroud)

返回

Msg 116 Level 16 State 1 Line 2 当子查询没有用EXISTS引入时,选择列表中只能指定一个表达式。

SELECT
CASE WHEN (SELECT 1 WHERE (1=1) UNION SELECT 2 WHERE (1=1)) = 1 THEN 1 ELSE 0 END
Run Code Online (Sandbox Code Playgroud)

返回

消息 512 级别 16 状态 1 第 1 行子查询返回了 1 个以上的值。当子查询跟随 =、!=、<、<=、>、>= 或当子查询用作表达式时,这是不允许的。