在SQL中,NULL是一种特有的数据类型,其等价于没知有任何值、是未知数。NULL与0、空道字符串、空格都不同。SQL默认情况下对WHERE XX!= Null的判断会永远返回0行,却不会提示语法错误。内容
非ANSI SQL标准中data=NULL等同于data IS NULL,data<>NULL等同于data IS NOT NULL。
所以:默认情况下做比较条件时使用关键字“is null”和“is not null”。
-- SQL 不报错,但查不出结果
SELECT * FROM t_sample_null WHERE remark = NULL;
三值逻辑
在主流的编程语言中(C、JAVA、Python、JS等)中,逻辑值确实只有 2 个,但在 SQL 中却存在第三个逻辑值:unknown。这有点类似于我们平时所说的:对、错、不知道。
逻辑值 unknown 和作为 NULL 的一种的 UNKNOWN (未知)是不同的东西。前者是明确的布尔型的逻辑值,后者既不是值也不是变量。为了便于区分,前者采用小写字母 unknown ,后者用大写字母 UNKNOWN 来表示。为了让大家理解两者的不同,我们来看一个 x=x 这样的简单等式。x 是逻辑值 unknown 时,x=x 被判断为 true ,而 x 是 UNKNOWN 时被判断为 unknown
-- 这个是明确的逻辑值的比较
unknown = unknown → true
-- 这个相当于NULL = NULL
UNKNOWN = UNKNOWN → unknown
三值逻辑的逻辑值表
NOT:
AND:
OR:
图中蓝色部分是三值逻辑中独有的运算,这在二值逻辑中是没有的。其余的 SQL 谓词全部都能由这三个逻辑运算组合而来。从这个意义上讲,这个几个逻辑表可以说是 SQL 的母体(matrix)。
NOT 的话,因为逻辑值表比较简单,所以很好记;但是对于 AND 和 OR,因为组合出来的逻辑值较多,所以全部记住非常困难。为了便于记忆,请注意这三个逻辑值之间有下面这样的优先级顺序。
AND 的情况: false > unknown > true
OR 的情况: true > unknown > false
优先级高的逻辑值会决定计算结果。例如 true AND unknown ,因为 unknown 的优先级更高,所以结果是 unknown 。而 true OR unknown 的话,因为 true 优先级更高,所以结果是 true 。记住这个顺序后就能更方便地进行三值逻辑运算了。特别需要记住的是,当 AND 运算中包含 unknown 时,结果肯定不会是 true (反之,如果AND 运算结果为 true ,则参与运算的双方必须都为 true )。
-- 假设 a = 2, b = 5, c = NULL,下列表达式的逻辑值如下
a < b AND b > c → unknown
a > b OR b < c → unknown
a < b OR b < c → true
NOT (b <> c) → unknown
“IS NULL” 而非 “= NULL”
我们再回到问题:为什么必须写成“IS NULL”,而不是“= NULL”
对 NULL 使用比较谓词后得到的结果总是 unknown 。而查询结果只会包含 WHERE 子句里的判断结果为 true 的行,不会包含判断结果为 false 和 unknown 的行。不只是等号,对 NULL 使用其他比较谓词,结果也都是一样的。所以无论 remark 是不是 NULL ,比较结果都是 unknown ,那么永远没有结果返回。以下的式子都会被判为 unknown
-- 以下的式子都会被判为 unknown
= NULL
> NULL
< NULL
<> NULL
NULL = NULL
那么,为什么对 NULL 使用比较谓词后得到的结果永远不可能为真呢?这是因为,NULL 既不是值也不是变量。NULL 只是一个表示“没有值”的标记,而比较谓词只适用于值。因此,对并非值的 NULL 使用比较谓词本来就是没有意义的。“列的值为 NULL ”、“NULL 值” 这样的说法本身就是错误的。因为 NULL不是值,所以不在定义域(domain)中。相反,如果有人认为 NULL 是值,那么我们可以倒过来想一下:它是什么类型的值?关系数据库中存在的值必然属于某种类型,比如字符型或数值型等。所以,假如 NULL 是值,那么它就必须属于某种类型。
NULL 容易被认为是值的原因有两个。第一个是高级编程语言里面,NULL 被定义为了一个常量(很多语言将其定义为了整数0),这导致了我们的混淆。但是,SQL 里的 NULL 和其他编程语言里的 NULL 是完全不同的东西。第二个原因是,IS NULL 这样的谓词是由两个单词构成的,所以我们容易把 IS 当作谓词,而把 NULL 当作值。特别是 SQL 里还有 IS TRUE 、IS FALSE 这样的谓词,我们由此类推,从而这样认为也不是没有道理。但是正如讲解标准 SQL 的书里提醒人们注意的那样,我们应该把 IS NULL 看作是一个谓词。因此,写成 IS_NULL 这样也许更合适。