SQL进价2:三值逻辑和null
Posted gds-1202b
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了SQL进价2:三值逻辑和null相关的知识,希望对你有一定的参考价值。
1、SQL中的bool类型的值有三种
普通编程语言里的布尔型只有 true
和 false
两个值,这种逻辑体系被称为二值逻辑。而 SQL 语言里,除此之外还有第三个值 unknown
,因此这种逻辑体系被称为三值逻辑(three-valued logic)。
2、null不是值,与数学运算符结果的结果永远是unknown
常听到的“列的值为 NULL
” 、“NULL
值”这样的说法本身就是错误的。因为 NULL
不是值,NULL
不是值NULL
不是值!(如果有人认为 NULL
是值,那么它是什么类型的值?关系数据库中存在的值必然属于某种类型,比如字符型或数值型等。所以,假如 NULL
是值,那么它就必须属于某种类型。)
另外,注意:要想和null比较只能用 is null 或者 is not null,这样才会返回true或者false。另外永远记住一点,null和<,<,=,<>这些放在一起结果永远是unknown,如 2=null,结果肯定是unknown,而unknown可在三值逻辑中不是true或者false,在写where子句的筛选条件时尤其要注意。举例来讲:
接下来我们总结一下 SQL 遵循的三值逻辑的真值规律(理解下面这些非常重要)。
先看下图:(t:true,f:false,u:unknown。not unknown 的结果是 unknown)
我们经常会遇到判断筛选条件的结果(为true/false/unknown的一种,且SQL只会取返回结果是true的记录),它们通常是and 或or连接这些单个条件的,如:where age>18 and sex=0或where age<18 and sex =unknown。所以我们要牢牢记住上面这个图,才能对各种情况下返回的数据心里有底。
记忆方式1:
and运算,只要有一边是unknown,另一边是false,那结果就是false,其它情况下,只要任意一边有unknown,结果就是unknown。
or运算,只要一边是unknown,那么结果永远就是unknown
记忆方式2:
在判断and或or的最终结果时,请注意true/false/unknown之间有下面这样的优先级顺序。
AND
的情况:false
>unknown
>true
OR
的情况:true
>unknown
>false
优先级高的真值会决定计算结果。例如 true AND unknown
,因为 unknown
的优先级更高,所以结果是 unknown
。而 true OR unknown
的话,因为 true
优先级更高,所以结果是 true
。记住这个顺序后就能更方便地进行三值逻辑运算了。特别需要记住的是,当 AND
运算中包含 unknown
时,结果肯定不会是 true
(反之,如果 AND
运算结果为 true
,则参与运算的双方必须都为 true
)。这一点对理解后文非常关键。
3、NOT IN 和 NOT EXISTS 不是等价的
如果 NOT IN
子查询中用到的表里被选择的列中存在 NULL
,则 SQL 语句整体的查询结果永远是空。EXISTS
谓词永远不会返回 unknown
。EXISTS
只会返回 true
或者 false
。因此就有了 IN
和 EXISTS
可以互相替换使用,而 NOT IN
和 NOT EXISTS
却不可以互相替换的混乱现象。
4、ALL
运算符与null
以下是ALL
运算符语法:
scalar_expression comparison_operator ALL ( subquery )
在上面语法中,
scalar_expression
是任何有效的表达式。comparison_operator
是任何有效的比较运算符,包括等于(=
),不等于(<>
),大于(>
),大于或等于(>=
),小于(<
),小于或等于(<=
)。- 括号内的子查询(
subquery
)是一个SELECT语句,它返回单个列的结果。 此外,返回列的数据类型必须与标量表达式的数据类型相同。
如果所有比较对(scalar_expression,v)
的计算结果为TRUE
,则ALL
运算符返回TRUE
; v
是单列结果中的值。
如果其中一对(scalar_expression,v)
返回FALSE
,则ALL
运算符返回FALSE
。
如果all里面的子查询返回的单列中有null的存在,那么这个all表达式就永远不会筛选出任何数据,结果肯定为空。
因为ALL
谓词其实是多个以 AND
连接的逻辑表达式的省略写法。
如果all里面的子查询返回的单列中有null的存在,比如子查询结果如下面这个情况,那么具体的分析步骤如下所示。
--1. 执行子查询获取年龄列表
SELECT *
FROM Class_A
WHERE age < ALL ( 22, 23, NULL );
--2. 将ALL 谓词等价改写为AND
SELECT *
FROM Class_A
WHERE (age < 22) AND (age < 23) AND (age < NULL);
--3. 对NULL 使用“<”后,结果变为 unknown
SELECT *
FROM Class_A
WHERE (age < 22) AND (age < 23) AND unknown;
--4. 如果AND 运算里包含unknown,则结果不为true
SELECT *
FROM Class_A
WHERE false 或 unknown;
--5.查询结果为空
以上是关于SQL进价2:三值逻辑和null的主要内容,如果未能解决你的问题,请参考以下文章