设为首页 - 加入收藏 ASP站长网(Aspzz.Cn)- 科技、建站、经验、云计算、5G、大数据,站长网!
热搜: 创业者 数据 手机
当前位置: 首页 > 站长学院 > MySql教程 > 正文

搞清这些陷阱,NULL和三值逻辑再也不会作妖(4)

发布时间:2019-11-07 20:19 所属栏目:115 来源:youzhibing2904
导读:我们发现结果是空,查询不到任何数据,这是为什么 ?这里 NULL 又开始作怪了,我们一步一步来看看究竟发生了什么。 --1.执行子查询,获取年龄列表 SELECT*FROMt_student WHEREageNOTIN(43,NULL,25); --2.用NOT和IN等

我们发现结果是空,查询不到任何数据,这是为什么 ?这里 NULL 又开始作怪了,我们一步一步来看看究竟发生了什么。

  1. -- 1. 执行子查询,获取年龄列表 
  2. SELECT * FROM t_student 
  3. WHERE age NOT IN(43, NULL, 25); 
  4.  
  5. -- 2. 用NOT 和IN 等价改写NOT IN 
  6. SELECT * FROM t_student 
  7. WHERE NOT age IN (43, NULL, 25); 
  8.  
  9. -- 3. 用OR 等价改写谓词IN 
  10. SELECT * FROM t_student 
  11. WHERE NOT ( (age = 43) OR (age = NULL) OR (age = 25) ); 
  12.  
  13. -- 4. 使用德· 摩根定律等价改写 
  14. SELECT * FROM t_student 
  15. WHERE NOT (age = 43) AND NOT(age = NULL) AND NOT (age = 25); 
  16.  
  17. -- 5. 用<> 等价改写 NOT 和 = 
  18. SELECT * FROM t_student 
  19. WHERE (age <> 43) AND (age <> NULL) AND (age <> 25); 
  20.  
  21. -- 6. 对NULL 使用<> 后,结果为 unknown 
  22. SELECT * FROM t_student 
  23. WHERE (age <> 43) AND unknown AND (age <> 25); 
  24.  
  25. -- 7.如果 AND 运算里包含 unknown,则结果不为true(参考三值逻辑的逻辑值表) 
  26. SELECT * FROM t_student 
  27. WHERE false 或 unknown; 

可以看出,在进行了一系列的转换后,没有一条记录在 WHERE 子句里被判断为 true 。也就是说,如果 NOT IN 子查询中用到的表里被选择的列中存在 NULL ,则 SQL 语句整体的查询结果永远是空。这是很可怕的现象!

为了得到正确的结果,我们需要使用 EXISTS 谓词。

  1. -- 正确的SQL 语句:马化腾和李彦宏将被查询到 
  2. SELECT * FROM t_student_B B 
  3. WHERE NOT EXISTS (  
  4.     SELECT * FROM t_student_A A 
  5.     WHERE B.age = A.age 
  6.     AND A.city = '深圳市'  
  7. ); 

执行结果如下:

搞清这些陷阱,NULL和三值逻辑再也不会作妖

同样地,我们再来一步一步地看看这段 SQL 是如何处理年龄为 NULL 的行的:

  1. -- 1. 在子查询里和 NULL 进行比较运算,此时 A.age 是 NULL 
  2. SELECT * FROM t_student_B B 
  3. WHERE NOT EXISTS (  
  4.     SELECT * FROM t_student_A A 
  5.     WHERE B.age = NULL 
  6.     AND A.city = '深圳市'  
  7. ); 
  8.  
  9. -- 2. 对NULL 使用“=”后,结果为 unknown 
  10. SELECT * FROM t_student_B B 
  11. WHERE NOT EXISTS (  
  12.     SELECT * FROM t_student_A A 
  13.     WHERE unknown 
  14.     AND A.city = '深圳市'  
  15. ); 
  16.  
  17. -- 3. 如果AND 运算里包含 unknown,结果不会是true 
  18. SELECT * FROM t_student_B B 
  19. WHERE NOT EXISTS (  
  20.     SELECT * FROM t_student_A A 
  21.     WHERE false 或 unknown 
  22. ); 
  23.  
  24. -- 4. 子查询没有返回结果,因此相反地,NOT EXISTS 为 true 
  25. SELECT * FROM t_student_B B 
  26. WHERE true; 

(编辑:ASP站长网)

网友评论
推荐文章
    热点阅读