(SQL 和 SQL Server 相对较新)我正在阅读Itzik Ben-Gan 撰写的 SQL Server 2012 T-SQL Fundamentals。作者声明:
SQL在不同的语言元素中对UNKNOWN有不同的处理
因此,我浏览了 SQL Server 文档,尤其是WHERE
clause,但找不到任何关于如何NULL/UNKNOWN
处理的具体内容。
有人可以指出我更正文档或指出我在文档中读错的内容吗?(我高度怀疑我的问题的答案深埋在 SQL 标准的某个地方,但它对我来说可能太复杂了,至少在这一点上是这样。)
不同条款中的处理方式
UNKNOWN
和处理方式存在细微差别。NULL
可以出现布尔表达式的三个子句是
WHERE
,HAVING
和FROM
(在ON
子句中)。在所有这三个中,以UNKNOWN
相同的方式对待。WHERE <boolean expression>
:如果表达式的计算结果为 ,则一行“通过”
<boolean expression>
and 被返回TRUE
。如果表达式的计算结果为FALSE
orUNKNOWN
,则该行不会通过并从查询的进一步计算中删除。HAVING <boolean expression>
:子句中检查的行
HAVING
是由前一个子句的聚合创建的GROUP BY
。类似于上面一行(由聚合创建)“传递”<boolean expression>
并且如果表达式计算为 则返回TRUE
。如果表达式的计算结果为FALSE
orUNKNOWN
,则该行不会通过并从查询的进一步计算中删除。a JOIN b ON <boolean expression>
:来自的每一行都
a
针对来自的每一行进行检查b
。如果表达式为TRUE
,则检查通过并且两行的组合对于查询的进一步处理是有效的。如果FALSE
或UNKNOWN
,则组合被拒绝。当连接是外部连接(
LEFT
,RIGHT
或FULL
)时会有轻微的变化,但与UNKNOWN
处理方式无关。这里发生的是,如果左表中的一行(在LEFT
连接中)与右表中的任何行都不匹配(即它的所有检查评估为FALSE
orUNKNOWN
),那么该行仍然被转发并且b
列的缺失值被填充空值。)情况在约束上有所不同,对.有更“宽松”的处理
UNKNOWN
。我想这首先与允许空值的决定有关。空值将导致UNKNOWN
大多数约束的结果,因此允许插入这些行是有意义的。否则,效果将与将列声明为 相同NOT NULL
。CHECK
约束:CHECK <expression>
TRUE
如果表达式的计算结果为或,则允许插入(或更新)行UNKNOWN
。仅当表达式的计算结果为 时,它才会被拒绝FALSE
。FOREIGN KEY
约束,具有可为空的列。类似于检查约束,如果一行在参与外键约束的列之一中有一个空值,
FOREIGN KEY
则跳过约束的验证并允许插入(或更新)该行。可以想到一个表中的外键约束a
:相当于:
因此,如果
a.column
isNULL
,则表达式被计算为UNKNOWN
,因此该行被允许。UNIQUE
约束这里 SQL-Server 偏离了标准,该标准规定如果具有唯一约束的行包含
NULL
,则跳过唯一检查并允许该行。SQL-Server 将空值视为常规值,当涉及到唯一约束并且在此类列中只允许一个
NULL
值时。NULL
值在某些条款中也有特殊待遇:GROUP BY
:如果分组列包含空值,则所有空值都被认为是相等的,并且它们被放入一个组中(同样的事情发生在
SELECT DISTINCT
查询中。)聚合函数(
MIN()
、MAX()
、和其他)忽略空值,但空值SUM()
可以做很多不同的事情:AVG()
COUNT()
COUNT(*)
并将COUNT(constant)
计算所有行。COUNT(column)
并且COUNT(expression)
会像其他聚合函数一样忽略空值,并且只计算列或表达式不为空的行。COUNT(DISTINCT column)
并且COUNT(DISTINCT expression)
还将忽略空值并仅计算不同的非空列或表达式。因此,如果列中存在空值,则以下 4 个查询可能会返回 4 个不同的结果:
ORDER BY
:NULL
值被视为相等。ASC
最后出现DESC
。(在最新的标准中定义了一个
NULLS LAST
andNULLS FIRST
属性,但是 SQL Server 还没有实现它。)