写点什么

如何正确理解 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:152530
用户头像
小智 让所有人认同的文字称不上表达

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

关注

评论 1 条评论

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

Chrome操作指南——入门篇(四) command

Augus

Chrome开发者工具 9月月更

大数据开发入门学习方法推荐

小谷哥

研发效能提升不来自于度量本身,而来自于针对性的改进

万事ONES

为什么C++能屹立这么久?细说C++ 可以开发的 7 件事 以及 C++ 的特点和学习的优点

C++后台开发

c++ C/C++ C++后台开发 C++开发 C++开发工程师

小程序转 App 帮助中小企业打开营销新窗口

FinClip

天翼云铸牢国云安全,护航千行百业

天翼云开发者社区

[MyBatisPlus]id生成策略控制

十八岁讨厌编程

Java spring 9月月更

物联网平台在AIoT领域8大场景应用

AIRIOT

低代码 物联网 低代码平台 低代码,项目开发

云行| 天翼云中国行走进宁波,推动千行百业迈向数字化转型之路

天翼云开发者社区

Chrome操作指南——入门篇(三)

Augus

Chrome开发者工具 9月月更

大数据生态安全框架的实现原理与最佳实践(下篇)

明哥的IT随笔

大数据 hdfs hive 数据安全

web前端培训开发技术前景怎么样?

小谷哥

车联网该怎样跳过车企设置的红线

Geek_99967b

小程序

如何深入学习前端培训技术知识

小谷哥

本周四晚19:00知识赋能第八期第1课丨ArkUI框架整体设计

OpenHarmony开发者

OpenHarmony

数据库高可靠,轻松解决事务丢失问题

天翼云开发者社区

小程序容器,让你快速控制智能家居

Geek_99967b

小程序 小程序容器

[MyBatisPlus]映射匹配兼容性

十八岁讨厌编程

Java 后端开发 9月月更

2022世界人工智能大会开幕,天翼云注智城市数字化转型

天翼云开发者社区

web前端培训课程哪家好

小谷哥

Java 将 Word 转换为PDF文档

在下毛毛雨

Java PDF word Word转PDF

一键小程序转换App,极低门槛实现组装式App

FinClip

忘记背后,努力面前【开学季flag】

Fire_Shield

程序人生 9月月更 开学季

墨天轮沙龙 | 庚顿数据姚羽:实时数据技术赋能流程工业,保障业务连续性

墨天轮

数据库 国产数据库 实时数据库

重磅启动!第 17 届「中国 Linux 内核开发者大会」征稿

OpenAnolis小助手

Linux 征稿 内核 开发者大会 龙蜥社区

打造国云安全品牌,铸牢企业云上安全防线

天翼云开发者社区

多因素身份认证 (MFA) 插件:手机验证码认证因素配置流程

龙归科技

开源 手机验证码认证

[MyBatisPlus]乐观锁、代码生成器

十八岁讨厌编程

Java 后端开发 9月月更

跳槽一次能涨多少?一份1500道大厂面试题笔记就够了,涨薪80%

程序知音

Java 程序员 java面试 后端技术 Java八股文

Chrome操作指南——入门篇(二)

Augus

Chrome开发者工具 9月月更

零基础学习大数据还是自学呢

小谷哥

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