【问题标题】:When does a query/subquery return a NULL and when no value at all?查询/子查询什么时候返回 NULL,什么时候根本没有值?
【发布时间】:2010-04-27 18:15:32
【问题描述】:
  1. 如果查询/子查询没有找到任何匹配的行,那么它要么返回 NULL,要么根本不返回值,因此甚至不返回 NULL 值。基于 查询/子查询返回 NULL 的条件是什么,什么时候不返回任何结果,甚至不返回 NULL 值?

  2. 如果没有,标量子查询是否总是返回 NULL 找到匹配的行?我假设最外部的标量查询也返回 如果没有找到行,则为 NULL?

  3. SELECT FirstName, LastName, YEAR(BirthDate)
    FROM Persons
    WHERE YEAR(BirthDate) IN (SELECT YearReleased FROM Albums);
    
    • 如果子查询没有找到结果,是外层的WHERE子句 查询翻译成WHERE YEAR(BirthDate) IN (null);

    • 如果 WHERE 子句被翻译成WHERE YEAR(BirthDate) IN();,那不应该是一个错误条件,因为YEAR(BirthDate) 的值怎么能与空值相提并论?

【问题讨论】:

    标签: sql sql-server subquery


    【解决方案1】:

    只有当YearReleasedNULL 时,子查询才会返回NULL,否则会有一个空记录集,这就是你提到的IN () 的情况。

    区分两者非常重要,因为它们的含义完全不同。 NULL 表示SELECTed 有一些东西要处理,尽管可以说该值表示“缺乏价值”。空记录集表示没有任何符合指定条件的选择。

    编辑:更新以显示示例结果

    前两个查询只是为了显示两个表中的内容。第三个查询是您的查询,第四个查询只是显示如果您将子查询替换为NULL,它会产生等效结果(无行)。最后一个查询只是为了表明子查询本身只是返回一个NULLs 的大列表。

    【讨论】:

    • “子查询只会在 YearReleased 为 NULL 时返回 NULL,否则会出现一个空记录集,这就是你提到的 IN () 情况。”换句话说,如果 Albums 表只包含行(比如 10 行)且 YearReleased 字段设置为 NULL,则子查询应生成 10 行的结果集,并且外部查询的 WHERE 子句应转换为 WHERE YEAR(BirthDate) IN (空)?!
    • 查看编辑,但是这就是 where 子句本质上会变成 WHERE YEAR(BirthDate) IN (NULL)
    • 我已经将您的帖子标记为答案,但如果您找到时间 --> 假设相册表不包含任何行,则 SELECT MAX(CDPrice) FROM Albums;查询仍然会产生一个结果集(单行),因为 MAX 函数的返回值( NULL )被认为是一行?!
    【解决方案2】:

    一个。如果没有匹配的行,则结果集将始终为空。 NULL 值没有任何特殊处理。

    b.这不是真的。如果没有匹配的行,则结果集根据定义始终为空。标量函数的结果不是结果集,因此它要么为 NULL,要么为其他值。

    c.1。如果子查询不返回任何行,则“IN”表达式将始终返回 false。该集合不会是NULL

    c.2。将YEAR(BirthDate) 与空集进行比较是有效的。它总是返回 false。

    【讨论】:

    • A)“c.1.如果子查询不返回任何行,则“IN”表达式将始终返回 false。该集合不会为 NULL。”我假设如果 Albums 表只包含行(比如 10 行),并且 YearReleased 字段设置为 NULL,那么子查询应该产生一个 10 行的结果集,并且外部查询的 WHERE 子句应该被翻译成 WHERE YEAR(BirthDate) IN (null );?! B) 假设 Albums 表不包含任何行,则 SELECT MAX(CDPrice) FROM Albums;查询仍然会产生一个结果集(单行),因为 MAX 函数的返回值( NULL )被认为是一行?!
    【解决方案3】:
    SELECT FirstName, LastName, YEAR(BirthDate)
    FROM Persons a
    left join (SELECT YearReleased FROM Albums) b on year(b.YearReleased) = year(a.BirthDate)
    where year(b.YearReleased) = year(a.BirthDate)
    

    【讨论】:

    • 这不会试图回答 OP 明确提出的问题。
    【解决方案4】:

    SQL 中有多种类型的子查询,您获得哪一种(以及产生的行为)取决于上下文。如果在大多数表达式上下文中使用(subquery) 语法作为操作数,则这是一个标量子查询。另一方面,作为IN运算符的右操作数,它是一个表子查询。

    对于标量子查询: 如果子查询没有返回行,标量子查询的结果是NULL。 如果子查询返回多行,则为错误。 如果子查询返回一行,则结果是该行的(唯一)查询列的值。

    对于表子查询: 如果子查询没有返回任何行,则结果是一组空值,例如IN 操作将始终返回 false。 否则,结果是所有行的查询列的集合。

    所以单独解决您的问题:

    1. 取决于子查询的上下文

    2. 是的,如果没有行,标量子查询总是返回 NULL 找到了

    3. IN 操作的上下文中,它是一个表子查询,并且 所以没有行意味着没有要匹配的值。但请注意,由于 到IN 的语义,如果您的查询返回查询所在的行 列值本身是NULL,您的列中将有一个NULL 比较集。 IN 操作实际上是相等的 OR 左操作数和每个值之间的比较 右手边的值集。集合中的空值将导致 “未知”而不是真或假,因此IN 操作可以 只返回 true (如果与某些非空值匹配 集合)或未知(因为该值可能匹配也可能不匹配 null)。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-10-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-04-18
      • 1970-01-01
      相关资源
      最近更新 更多