限时领|《AI 百问百答》专栏课+实体书(包邮)! 了解详情
写点什么

如何正确理解 SQL 中的 NULL

  • 2020-04-01
  • 本文字数:1811 字

    阅读完需:约 6 分钟

如何正确理解SQL中的NULL

在查询数据库时,如果你想知道一个列是否为 NULL,SQL 查询语句该怎么写呢?


是不是这样:


SELECT * FROM SOME_TABLEWHERE SOME_COLUMN = NULL
复制代码


或者这样写:


SELECT * FROM SOME_TABLEWHERE SOME_COLUMN IS NULL
复制代码


正确的写法应该是第二种(WHERE SOME_COLUMN IS NULL)。


为什么要这样写?


在进行数据库数据比较操作时,我们不会使用“IS”关键词,不是吗?


例如,如果我们想要知道一个列的值是否等于 1,WHERE 语句是这样的:


WHERE SOME_COLUMN = 1
复制代码


那为什么 NULL 值要用 IS 关键字呢?为什么要以这种方式来处理 NULL?


因为,在 SQL 中,NULL 表示“未知”。也就是说,NULL 值表示的是“未知”的值。

NULL 等于未知

在大多数数据库中,NULl 和空字符串是有区别的。


但并不是所有数据库都这样,例如,Oracle 就不支持空字符串,它会把空字符串自动转成 NULL 值。


在其他大多数数据库里,NULL 值和字符串的处理方式是不一样的:


  • 空字符串表示“没有值”,这个值是已知的。

  • NULL 表示“未知值”,这个值是未知的。


这就好比我问了一个问题:“美国总统罗斯福的中间名是什么”?


  • 可能有人会回答说:“我不知道罗斯福总统的中间名是什么”。对于这种情况,可以在数据库中使用 MIDDLE_NAME 列来表示罗斯福的中间名,而这一列的值为 NULL。

  • 也可能有人会回答说:“罗斯福总统没有中间名。他的父母没有给他取中间名,所以我知道罗斯福总统确实没有中间名”。对于这种情况,MIDDLE_NAME 列应该是一个空字符串。


Oracle 比较特殊,两个值都使用 NULL 来表示,而其他大多数数据库会区分对待。


但只要记住 NULL 表示的是一个未知的值,那么在写 SQL 查询语句时就会得心应手。


例如,如果你有一个这样的查询语句:


SELECT * FROM SOME_TABLEWHERE 1 = 1
复制代码


这个查询会返回所有的行(假设 SOME_TABLE 不是空表),因为表达式“1=1”一定为 true。


如果我这样写:


SELECT * FROM SOME_TABLEWHERE 1 = 0
复制代码


表达式“1=0”是 false,这个查询语句不会返回任何数据。


但如果我写成这样:


SELECT * FROM SOME_TABLEWHERE 1 = NULL
复制代码


这个时候,数据库不知道这两个值(1 和 NULL)是否相等,所以它也不会返回任何数据。

三元逻辑

SQL 查询语句中的 WHERE 一般会有三种结果:


  • 它可以是 true(这个时候会返回数据);

  • 它可以是 false(这个时候不会返回数据);

  • 它也可以是 NULL 或未知(这个时候也不会返回数据)。


你可能会想:“既然这样,那我为什么要去关心是 false 还是 NULL?它们不是都不会返回数据吗?”


接下来,我来告诉你在哪些情况下会有问题:我们来看看 NOT()。


假设有这样的一个查询语句:


SELECT * FROM SOME_TABLEWHERE NOT(1 = 1)
复制代码


数据库首先会计算 1=1,这个显然是 true。


接着,数据库会应用 NOT() 条件,所以 WHERE 返回 false。


所以,上面的查询不会返回任何数据。


但如果把语句改成这样:


SELECT * FROM SOME_TABLEWHERE NOT(1 = 0)
复制代码


数据库首先会计算 1=0,这个肯定是 false。


接着,数据库应用 NOT() 条件,这样就得到相反的结果,变成了 true。


所以,这个语句会返回数据。


但如果把语句再改成下面这样呢?


SELECT * FROM SOME_TABLEWHERE NOT(1 = NULL)
复制代码


数据库首先计算 1=NULL,它不知道 1 是否等于 NULL,因为它不知道 NULL 的值是什么。


所以,这个计算不会返回 true,也不会返回 false,它会返回一个 NULL。


接下来,NOT() 会继续解析上一个计算返回的结果。


当 NOT() 遇到 NULL,它会生成另一个 NULL。未知的相反面是另一个未知。


所以,对于这两个查询:


SELECT * FROM SOME_TABLEWHERE NOT(1 = NULL)
复制代码



SELECT * FROM SOME_TABLEWHERE 1 = NULL
复制代码


都不会返回数据,尽管它们是完全相反的。

NULL 和 NOT IN

如果我有这样的一个查询语句:


SELECT * FROM SOME_TABLEWHERE 1 IN (1, 2, 3, 4, NULL)
复制代码


很显然,WHERE 返回 true,这个语句将返回数据,因为 1 在括号列表里是存在的。


但如果这么写:


SELECT * FROM SOME_TABLEWHERE 1 NOT IN (1, 2, 3, 4, NULL)
复制代码


很显然,WHERE 返回 false,这个查询不会返回数据,因为 1 在括号列表里存在,但我们说的是“NOT IN”。


但如果我们把语句改成这样呢?


SELECT * FROM SOME_TABLEWHERE 5 NOT IN (1, 2, 3, 4, NULL)
复制代码


这里的 WHRE 不会返回数据,因为它的结果不是 true。数字 5 在括号列表里可能不存在,也可能存在,因为当中有一个 NULL 值(数据库不知道 NULL 的值是什么)。


这个 WHERE 会返回 NULL,所以整个查询不会返回任何数据。


希望你们现在都清楚该怎么在 SQL 语句中处理 NULL 值了。

英文原文

Null Values in SQL Queries


2020-04-01 14:152682
用户头像
小智 让所有人认同的文字称不上表达

发布了 408 篇内容, 共 400.4 次阅读, 收获喜欢 1985 次。

关注

评论 1 条评论

发布
用户头像
涨姿势了,以前确实没有好好思考过null的问题
2020-04-01 23:44
回复
没有更多了
发现更多内容

Go Channel源码分析

非晓为骁

源码分析 channel Go 语言

数据仓库设计

大数据技术指南

大数据 28天写作 3月日更

Spark详细剖析

五分钟学大数据

大数据 spark 28天写作 3月日更

科技强国的使命召唤中,百度AI埋下三根未来“引线”

脑极体

Java8中的 Stream 那么彪悍,你知道它的原理是什么吗?

Java小咖秀

Java 面试 stream java8 开发

银行业只是开始,60个可以被区块链改变的行业

CECBC

数字技术

2021十大区块链领域即将起飞

CECBC

区块链 投资

为何数字人民币要采用“小额匿名、大额可溯”的设计?

CECBC

数字货币

产品训练营第八周作业——用户路径地图

innovator琳

用户研究 用户地图 用户数据 用户模型

谈兼职创业

Ryan Zheng

OpenCV 写图像也有讲究,取经之路第 5 天

梦想橡皮擦

28天写作 3月日更

央行数字人民币“可控匿名”会侵犯隐私吗?最新解读来了

CECBC

数字货币

一文搞定Diff算法

执鸢者

Vue 大前端 Diff

传统IT部门为什么越来越不受欢迎?

boshi

数字化转型 IT职场 七日更

探索 Snabbdom 模块系统原理

Geek_z9ygea

JavaScript Vue Web Vue 3 Snabbdom

从Nacos客户端视角来分析配置中心原理

麦洛

nacos SpringCloud Alibaba 动态配置

用户故事拆分速查手册(译)

Bruce Talk

敏捷 译文 Agile User Story

找到适合自己的睡眠方案

石云升

生活方式 28天写作 睡眠 3月日更

Vue3源码 | createApp都干了什么?

梁龙先森

源码分析 大前端 Vue3

工作多年后我更明白了UT的重要性

好好学习,天天向上

hive数据倾斜解决办法

五分钟学大数据

大数据 hive 28天写作 3月日更

IO 模型

无心

Netty

《青春有你3》的子弹时间舞台,凝筑了自由视角技术进化史

脑极体

大数据中流量分析常见分类

大数据技术指南

大数据 28天写作 3月日更

架构师训练营 4 期 第12周

引花眠

架构师训练营 4 期

产品训练营第八章作业

Arnold

线上问题的一点反思

风翱

复盘 3月日更 线上问题

控制台的安装与使用 | 联盟链开发(二)

李大狗

联盟链 FISCO BCOS 狗哥

Docker 教程(三):Docker 命令

看山

Docker

2.3 Go语言从入门到精通:数据类型

xcbeyond

3月日更 Go 语言

产品0期-第九周

Jxin

如何正确理解SQL中的NULL_数据库_MITCHUM_InfoQ精选文章