SQL 查询中的 NULL 值

image

本文通过各种 SQL 小例子,解释 NULL 值的用途和带来的问题。

英语原文地址:https://mitchum.blog/null-values-in-sql-queries/

作者:MITCHUM

翻译:高行行

参考翻译文章:https://blog.csdn.net/lnotime/article/details/104847946

小结:

  • SQL 里的 NULL 和其他编程语言里的 NULL 是完全不同的东西
  • 在 SQL 中 NULL 为未知

翻译水平有限,可能存在翻译不准确的地方,尽情谅解。

今天的帖子是关于 SQL 中的 NULL 值的,由我的朋友兼数据库向导 Kaley 提供。如果你想了解有关 SQL,Oracle 数据库以及使查询运行更快的更多信息,请访问他的网站


这是一个使很多萌新开发人员陷入困境的话题-SQL 查询中 NULL 值的概念。

每当你向数据库发出SQL查询时……你想知道一列中是否包含 NULL 值……编写查询以查到结果的正确方式是什么?

你应该使用这样的查询吗?

SELECT * FROM SOME_TABLE
WHERE SOME_COLUMN = NULL

要么!你应该使用这样的查询吗?

SELECT * FROM SOME_TABLE
WHERE SOME_COLUMN IS NULL

…答案是,你应该使用第二个查询(SOME_COLUMN IS NULL)。

下图为实际的查询例子 🌰

[图片上传失败...(image-3f58f1-1586060321607)]

[图片上传失败...(image-a119ac-1586060321607)]

[图片上传失败...(image-e0306a-1586060321607)]

为什么呢?

为什么其他的比较都不用 IS 关键字呢?

如果我们想知道一个字段是否等于 1,我们可以使用如下的 WHERE 子句:

WHERE SOME_COLUMN = 1

那么为什么我们在IS关键字上使用 NULL 值呢?为什么我们需要区别对待 NULL ?

答案是这样的:在 SQL 中,NULL 表示“未知”的概念 _ _(因此 NULL 值表示“未知”值)。

1. Null 为未知

在大多数数据库中,NULL 和空字符串(由双撇号 "" 或 '' 表示)之间存在差异。

但是,并非所有数据库都这样:例如,Oracle 数据库不允许你使用空字符串。任何时候 Oracle 数据库看到一个空字符串,它都会自动将空字符串转换为 NULL 值。

但是,对于大多数其他数据库,NULL 值与空字符串的处理方式不同:

  • 空字符串被视为没有值的已知值
  • 将 NULL 值视为未知值

举个例子,就好像问:美国总统西奥多·罗斯福的中间名是什么?

  • 一种答案可能是:“嗯,我不知道西奥多·罗斯福的中间名是什么。”(此想法可以由 Theodore Roosevelt 的记录的 MIDDLE_NAME 列中的 NULL 值表示,即中间名字段为 NULL)
  • 另一种答案可能是**“西奥多·罗斯福总统实际上没有中间名。他的父母从未给他起过中间名,我知道的事实就是西奥多·罗斯福(Theodore Roosevelt)没有中间名。 **(你可以通过在 MIDDLE_NAME 列中输入一个空字符串或 '' 来表示,即中间名字段为空字符串)

Oracle 数据库是最显著的例外,其中这两个值实际上都将由 NULL 表示-除 Oracle 以外的大多数数据库对 NULL 和空字符串的处理方式都非常不同。

只要你记得 NULL 值代表一个未知值,那么这将有助于你编写 SQL 查询,并帮助你解决使用 NULL 值可能遇到的一些棘手情况。

例如,如果你要使用这样的 WHERE 子句查询:

SELECT * FROM SOME_TABLE
WHERE 1 = 1

该查询将返回行(假设 SOME_TABLE 不是空表!),因为表达式“ 1 = 1” 可证明是 true 的……它可以被证明是正确的。

image
image

如果我要说:

SELECT * FROM SOME_TABLE
WHERE 1 = 0

然后数据库将看到此情况,并将“ 1 = 0”评估为 false(这意味着该查询将永远不会返回任何行)。

image
image

但是如果我要说:

SELECT * FROM SOME_TABLE
WHERE 1 = NULL

数据库基本上是这样的:“我不知道这两个值(1 和我们的黑盒 NULL 值)是否相等”……因此它不返回任何记录。

image
image

2. 三值逻辑

当 SQL 查询中有 WHERE 子句时,它可以具有三种不同结果之一:

  • true(它将返回行)
  • false(不会返回行)
  • NULL(未知也不会返回行)

你可能会想,“好吧,既然数据库对这两个值的处理完全相同,我为什么要关心 false 和 null 之间的区别?”

好吧,让我告诉你哪里可能遇到麻烦:让我们介绍一下 NOT() 条件。

如果你要说:

SELECT * FROM SOME_TABLE
WHERE NOT(1 = 1)

然后,数据库首先要求值 1 = 1,然后说:“好吧,那显然是对的。”

但是随后它将对其应用 NOT() 条件。“当 true 被 NOT() 修饰时,它变成了 false……所以 NOT() 条件导致我们的 WHERE 子句在这里是 false 的。”

因此,上面的查询不会返回任何记录。

[图片上传失败...(image-e9f5e4-1586060321607)]

但是,如果你要说:

SELECT * FROM SOME_TABLE
WHERE NOT(1 = 0)

然后,数据库首先计算表达式 1 = 0,并说:“那显然是 false 的。”

但是然后它将应用 NOT() 条件,这将给我们相反的结果,因此它变为 true

因此此查询将返回记录!

[图片上传失败...(image-cf44f3-1586060321607)]

如果我发出以下查询怎么办?

SELECT * FROM SOME_TABLE
WHERE NOT(1 = NULL)

数据库首先要评估 1 = NULL。(请记住,它将把 NULL 当作一个未知值!)

它会说:“我不能说 1 是否等于 NULL,因为我不知道 NULL(未知)值是什么。”

因此,它不会产生 true 的结果也不会产生 false 的结果 – 而是会产生 NULL(未知)结果。

NULL 结果将由 NOT() 运算符修饰。

每当你使用 NULL 并将其置于 NOT() 条件时……结果就是另一个 NULL!(未知的反面是……嗯……另一个未知)。

image
image

因此,NOT() 运算符对 null 条件不做任何事情。

所以这些查询中的……

SELECT * FROM SOME_TABLE
WHERE NOT(1 = NULL)
SELECT * FROM SOME_TABLE
WHERE 1 = NULL

…将不返回任何记录…即使它们是相反的!

image
image

3. NULL 和 NOT IN

如果我使用 WHERE 子句发出这样的查询:

SELECT * FROM SOME_TABLE
WHERE 1 IN (1, 2, 3, 4, NULL)

…那么显然 WHERE 子句将是 true 的,由于 1 在我们的 IN 列表中,所以该查询将返回记录…

[图片上传失败...(image-92c86b-1586060321607)]

但是如果我要说:

SELECT * FROM SOME_TABLE
WHERE 1 NOT IN (1, 2, 3, 4, NULL)

那么显然这将是 false 的,该查询将永远不会返回记录,因为数字 1 出现在我们的 IN 列表中,并且我们说“ NOT IN”…

[图片上传失败...(image-ffae2d-1586060321607)]

现在,如果我要说这样的话怎么办?

SELECT * FROM SOME_TABLE
WHERE 5 NOT IN (1, 2, 3, 4, NULL)

此 WHERE 子句将永远不会返回任何记录,因为它不是真正的可证明(它不能被证明是 true 的)。数字 5 没有明确出现在“ IN”列表中 - 但是 5 可能在我们的“黑盒” NULL 值内(数据库不一定知道 NULL 的值是什么)。

这将产生 NULL 结果(表示未知结果),因此 WHERE 子句永远不会返回任何记录。

[图片上传失败...(image-4dd578-1586060321607)]

这就是为什么将 NULL 值等效为未知值很重要的原因 - 每当你编写复杂的SQL查询时,它都会为你提供帮助。

希望你现在已经准备好处理 SQL 查询中的 NULL 值!有关 SQL,Oracle 数据库以及使查询运行更快的更多信息,请访问 blog.tuningsql.com

资料

实际例子 🌰的 SQL 文件

CREATE TABLE `user` (
  `id` int(25) NOT NULL AUTO_INCREMENT,
  `name` varchar(255) DEFAULT NULL,
  `age` int(32) DEFAULT NULL,
  `sex` varchar(255) DEFAULT NULL,
  `password` varchar(255) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8mb4;

INSERT INTO `test`.`user`(`id`, `name`, `age`, `sex`, `password`) VALUES (2, '小白', 1, '0', '333');
INSERT INTO `test`.`user`(`id`, `name`, `age`, `sex`, `password`) VALUES (3, 'white', 12, '0', '111');
INSERT INTO `test`.`user`(`id`, `name`, `age`, `sex`, `password`) VALUES (4, 'white', NULL, '0', '222');

参考文章

神奇的 SQL 之温柔的陷阱 → 三值逻辑 与 NULL !

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 157,373评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 66,732评论 1 290
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 107,163评论 0 238
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,700评论 0 202
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,036评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,425评论 1 211
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,737评论 2 310
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,421评论 0 194
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,141评论 1 239
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,398评论 2 243
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,908评论 1 257
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,276评论 2 251
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,907评论 3 233
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,018评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,772评论 0 192
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,448评论 2 269
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,325评论 2 261

推荐阅读更多精彩内容

  • 1. SQL 简介 SQL 的目标 理想情况下,数据库语言应允许用户: 建立数据库和关系结构 完成基本数据管理任务...
    板蓝根plank阅读 2,280评论 0 11
  • ORACLE自学教程 --create tabletestone ( id number, --序号usernam...
    落叶寂聊阅读 1,008评论 0 0
  • 什么是数据库? 数据库是存储数据的集合的单独的应用程序。每个数据库具有一个或多个不同的API,用于创建,访问,管理...
    chen_000阅读 4,005评论 0 19
  • 第三课: 排序检索数据 distinct关键字:distinct 列名1,列名2,列名3DISTINCT 关键字会...
    VictorBXv阅读 1,437评论 0 8
  • 今天看《我是特种兵二》,看了一会儿,怎么也看不进去了,先入为主,第一部分印象太深,很多角色给人的印象太深,到了第二...
    似悦阅读 112评论 0 1