当前位置: 首页 > article >正文

SQL的三值逻辑

 SQL除了有true和false两个值外,还有第3个值unknown(因为数据库引进了NULL),这种逻辑体系被称为三值逻辑。

1 三值逻辑

为什么必须写成“IS NULL,而不是“= NULL”?

SELECT * FROM t_table WHERE col_1 = NULL;

这条语句永远查询不出结果,因为对NULL使用比较谓词(=、>或<)后得到的结果总是unknown(NULL既不是值也不是变量,它只是一个表示“没有值”的标记,而比较谓词只适用于值。因此,对并非值的NULL使用比较谓词本来就没有意义的)。

!unknown= unknown
unknown or TRUE = TRUE
unknown or FALSE = unknown
unknown AND FALSE = FALSE
unknown AND TRUE = unknown

1.1 实践

1.1.1 排中律不成立

命题:小李是20岁,或者不是20岁。

在现实世界中,这是一个真命题。这种在二值逻辑中的命题被称为排中律。

SELECT * FROM t_student WHERE age = 20 OR age != 20;

上面这条sql 当遇到age 字段为空的数据时,将获取不到这行。 即 NULL = 20 OR NULL != 20 => unknown

1.1.2 NOT IN 和 NOT EXISTS 不是等价的

SELECT * FROM t_student1 WHERE age NOT IN (SELECT age FROM t_student2);

上面这条sql当t_student2表中存在age为空的数据时,将永远获取不到数据。

age NOT IN (12,NULL) => age != 12 AND age != NULL => unknown 或者FALSE,改成以下sql,将能得到正确结果。

SELECT * FROM t_student1 s1 WHERE NOT EXISTS ( SELECT * FROM t_student2 s2 WHERE s1.age = s2.age);

EXISTS 谓词永远不会返回unknown,只会返回true或者false。

1.1.3 限定谓词和极值函数

SQL 里有ALL和ANY两个限定谓词。ANY 与 IN 是等价的。ALL可以和比较谓词一起使用,表达“与所有的都相等”或“比所有的都大”等。

SELECT * FROM t_student1 WHERE age > ALL (SELECT age FROM t_student2);

上面的sql表示找出t_student1 表中age字段比t_student2表的age字段都大的数据。如果t_student2 表中所有数据的age字段都不为空,那么上面的sql能检索出正确的数据,但是如果t_student2表存在age字段为空的数据,那么这条sql将永远无法检索出数据。

可以用极值函数改进上面的SQL。

SELECT * FROM t_student1 WHERE age > SELECT MAX(age) FROM t_student2;

使用极值函数,当t_student2存在为NULL的数据时,将会忽略掉这条数据。但是,如果t_student2 是个空表,或者改变所有数据的age字段都为NULL时,极值函数将返回NULL。

实际上,当输入为空表时,返回NULL的不止是极值函数,除COUNT以外(如SUM、AVG等)的聚合函数也是如此。

1.1.4 字符串与NULL

在MySQL及大部分数据库中,NULL与字符串的连接,将会返回NULL,例如CONCAT(‘a’,NULL) => NULL。

但是在Oracle中,处理空字符串与NULL的规则和其他数据库不太一样:

1.原则上将空字符作为NULL进行处理。

SELECT * FROM t_student WHERE `name` IS NULL;

这条SQL能检索到字段name为NULL或者为空字符的数据。

 2.仅在进行字符串连接时,才将NULL视为空字符。

CONCAT(‘abc’,NULL) => abc

3.字符连接运算时,仅当两个运算对象都是NULL的情况才将它们视为NULL。

CONCAT(NULL,NULL) => NULL


http://www.kler.cn/a/390960.html

相关文章:

  • 深入理解BERT模型配置:BertConfig类详解
  • 在 Service Worker 中caches.put() 和 caches.add()/caches.addAll() 方法他们之间的区别
  • 《MYSQL45讲》误删数据怎么办
  • 【深度解析】CSS工程化全攻略(1)
  • Java 网络编程(一)—— UDP数据报套接字编程
  • GitLab基于Drone搭建持续集成(CI/CD)
  • 基于vue框架的的汽车租赁系统34311(程序+源码+数据库+调试部署+开发环境)系统界面在最后面。
  • HTML查缺补漏
  • playwright学习记录2--定位方式
  • 【Unity/GameFramework】Start Force ——配置和表加载
  • 二分答案-整型二分—愤怒的牛-P1676 [USACO05FEB] Aggressive cows G
  • 微服务架构面试内容整理-监控与追踪-Zipkin
  • AlphaFold3中文安装教程
  • Unity类银河战士恶魔城学习总结(P117 Ice And Fire Item Effec 制作一把冰火属性的剑)
  • 练习题 - Django 4.x WWW 网址使用示例和配置方法
  • Git推送报错Authentication failed
  • 深入探讨钉钉与金蝶云星空的数据集成技术
  • 在linux上搭建一个nodejs服务_全流程
  • 如何将交叉编译配置在环境变量中
  • arcgis for js实现popupTemplate弹窗field名称和值转义
  • 【MySQL 保姆级教学】事务的自动提交和手动提交(重点)--上(13)
  • 【开源免费】基于SpringBoot+Vue.JS宠物咖啡馆平台(JAVA毕业设计)
  • uniapp的基本使用(easycom规范和条件编译)和uview组件的安装和使用
  • 天地图入门|标注|移动飞行|缩放,商用地图替换
  • 自动化新时代:机器取代工作,我们该如何重塑自我?
  • 企业级工位管理:Spring Boot解决方案