我们发现结果是空,查询不到任何数据,这是为什么 ?这里 NULL 又开始作怪了,我们一步一步来看看究竟发生了什么。
- -- 1. 执行子查询,获取年龄列表
- SELECT * FROM t_student
- WHERE age NOT IN(43, NULL, 25);
-
- -- 2. 用NOT 和IN 等价改写NOT IN
- SELECT * FROM t_student
- WHERE NOT age IN (43, NULL, 25);
-
- -- 3. 用OR 等价改写谓词IN
- SELECT * FROM t_student
- WHERE NOT ( (age = 43) OR (age = NULL) OR (age = 25) );
-
- -- 4. 使用德· 摩根定律等价改写
- SELECT * FROM t_student
- WHERE NOT (age = 43) AND NOT(age = NULL) AND NOT (age = 25);
-
- -- 5. 用<> 等价改写 NOT 和 =
- SELECT * FROM t_student
- WHERE (age <> 43) AND (age <> NULL) AND (age <> 25);
-
- -- 6. 对NULL 使用<> 后,结果为 unknown
- SELECT * FROM t_student
- WHERE (age <> 43) AND unknown AND (age <> 25);
-
- -- 7.如果 AND 运算里包含 unknown,则结果不为true(参考三值逻辑的逻辑值表)
- SELECT * FROM t_student
- WHERE false 或 unknown;
可以看出,在进行了一系列的转换后,没有一条记录在 WHERE 子句里被判断为 true 。也就是说,如果 NOT IN 子查询中用到的表里被选择的列中存在 NULL ,则 SQL 语句整体的查询结果永远是空。这是很可怕的现象!
为了得到正确的结果,我们需要使用 EXISTS 谓词。
- -- 正确的SQL 语句:马化腾和李彦宏将被查询到
- SELECT * FROM t_student_B B
- WHERE NOT EXISTS (
- SELECT * FROM t_student_A A
- WHERE B.age = A.age
- AND A.city = '深圳市'
- );
执行结果如下:

同样地,我们再来一步一步地看看这段 SQL 是如何处理年龄为 NULL 的行的:
- -- 1. 在子查询里和 NULL 进行比较运算,此时 A.age 是 NULL
- SELECT * FROM t_student_B B
- WHERE NOT EXISTS (
- SELECT * FROM t_student_A A
- WHERE B.age = NULL
- AND A.city = '深圳市'
- );
-
- -- 2. 对NULL 使用“=”后,结果为 unknown
- SELECT * FROM t_student_B B
- WHERE NOT EXISTS (
- SELECT * FROM t_student_A A
- WHERE unknown
- AND A.city = '深圳市'
- );
-
- -- 3. 如果AND 运算里包含 unknown,结果不会是true
- SELECT * FROM t_student_B B
- WHERE NOT EXISTS (
- SELECT * FROM t_student_A A
- WHERE false 或 unknown
- );
-
- -- 4. 子查询没有返回结果,因此相反地,NOT EXISTS 为 true
- SELECT * FROM t_student_B B
- WHERE true;
(编辑:晋中站长网)
【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!
|