本文经过各类 SQL 小例子,解释 NULL 值的用途和带来的问题。html
英语原文地址:mitchum.blog/null-values…web
做者:MITCHUMsql
翻译:高行行数据库
参考翻译文章:blog.csdn.net/lnotime/art…编程
小结:编程语言
- SQL 里的 NULL 和其余编程语言里的 NULL 是彻底不一样的东西
- 在 SQL 中 NULL 为未知
翻译水平有限,可能存在翻译不许确的地方,尽情谅解。网站
今天的帖子是关于 SQL 中的 NULL 值的,由个人朋友兼数据库向导 Kaley 提供。若是你想了解有关 SQL,Oracle 数据库以及使查询运行更快的更多信息,请访问他的网站。ui
这是一个使不少萌新开发人员陷入困境的话题-SQL 查询中 NULL 值的概念。spa
每当你向数据库发出SQL查询时……你想知道一列中是否包含 NULL 值……编写查询以查到结果的正确方式是什么?.net
你应该使用这样的查询吗?
SELECT * FROM SOME_TABLE
WHERE SOME_COLUMN = NULL
复制代码
要么!你应该使用这样的查询吗?
SELECT * FROM SOME_TABLE
WHERE SOME_COLUMN IS NULL
复制代码
…答案是,你应该使用第二个查询(SOME_COLUMN IS NULL)。
下图为实际的查询例子 🌰
为何呢?
为何其余的比较都不用 IS 关键字呢?
若是咱们想知道一个字段是否等于 1,咱们可使用以下的 WHERE 子句:
WHERE SOME_COLUMN = 1
复制代码
那么为何咱们在IS关键字上使用 NULL 值呢?为何咱们须要区别对待 NULL ?
答案是这样的:在 SQL 中,NULL 表示“未知”的概念 _ _(所以 NULL 值表示“未知”值)。
在大多数数据库中,NULL 和空字符串(由双撇号 "" 或 '' 表示)之间存在差别。
可是,并不是全部数据库都这样:例如,Oracle 数据库不容许你使用空字符串。任什么时候候 Oracle 数据库看到一个空字符串,它都会自动将空字符串转换为 NULL 值。
可是,对于大多数其余数据库,NULL 值与空字符串的处理方式不一样:
举个例子,就好像问:美国总统西奥多·罗斯福的中间名是什么?
Oracle 数据库是最显著的例外,其中这两个值实际上都将由 NULL 表示-除 Oracle 之外的大多数数据库对 NULL 和空字符串的处理方式都很是不一样。
只要你记得 NULL 值表明一个未知值,那么这将有助于你编写 SQL 查询,并帮助你解决使用 NULL 值可能遇到的一些棘手状况。
例如,若是你要使用这样的 WHERE 子句查询:
SELECT * FROM SOME_TABLE
WHERE 1 = 1
复制代码
该查询将返回行(假设 SOME_TABLE 不是空表!),由于表达式“ 1 = 1” 可证实是 true 的……它能够被证实是正确的。
若是我要说:
SELECT * FROM SOME_TABLE
WHERE 1 = 0
复制代码
而后数据库将看到此状况,并将“ 1 = 0”评估为 false(这意味着该查询将_永远不会_返回任何行)。
可是若是我要说:
SELECT * FROM SOME_TABLE
WHERE 1 = NULL
复制代码
数据库基本上是这样的:“我不知道这两个值(1 和咱们的黑盒 NULL 值)是否相等”……所以它不返回任何记录。
当 SQL 查询中有 WHERE 子句时,它能够具备三种不一样结果之一:
你可能会想,“好吧,既然数据库对这两个值的处理彻底相同,我为何要关心 false 和 null 之间的区别?”
好吧,让我告诉你哪里可能遇到麻烦:让咱们介绍一下 NOT() 条件。
若是你要说:
SELECT * FROM SOME_TABLE
WHERE NOT(1 = 1)
复制代码
而后,数据库首先要求值 1 = 1,而后说:“好吧,那显然是对的。”
可是随后它将对其应用 NOT() 条件。“当 true 被 NOT() 修饰时,它变成了 false……因此 NOT() 条件致使咱们的 WHERE 子句在这里是 false 的。”
所以,上面的查询不会返回任何记录。
可是,若是你要说:
SELECT * FROM SOME_TABLE
WHERE NOT(1 = 0)
复制代码
而后,数据库首先计算表达式 1 = 0,并说:“那显然是 false 的。”
可是而后它将应用 NOT() 条件,这将给咱们相反的结果,所以它变为 true。
所以此查询将返回记录!
若是我发出如下查询怎么办?
SELECT * FROM SOME_TABLE
WHERE NOT(1 = NULL)
复制代码
数据库首先要评估 1 = NULL。(请记住,它将把 NULL 看成一个未知值!)
它会说:“我不能说 1 是否等于 NULL,由于我不知道 NULL(未知)值是什么。”
所以,它不会产生 true 的结果,也不会产生 false 的结果 – 而是会产生 NULL(未知)结果。
NULL 结果将由 NOT() 运算符修饰。
每当你使用 NULL 并将其置于 NOT() 条件时……结果就是另外一个 NULL!(未知的反面是……嗯……另外一个未知)。
所以,NOT() 运算符对 null 条件不作任何事情。
因此这些查询中的……
SELECT * FROM SOME_TABLE
WHERE NOT(1 = NULL)
复制代码
SELECT * FROM SOME_TABLE
WHERE 1 = NULL
复制代码
…将不返回任何记录…即便它们是相反的!
若是我使用 WHERE 子句发出这样的查询:
SELECT * FROM SOME_TABLE
WHERE 1 IN (1, 2, 3, 4, NULL)
复制代码
…那么显然 WHERE 子句将是 true 的,因为 1 在咱们的 IN 列表中,因此该查询将返回记录…
可是若是我要说:
SELECT * FROM SOME_TABLE
WHERE 1 NOT IN (1, 2, 3, 4, NULL)
复制代码
那么显然这将是 false 的,该查询将永远不会返回记录,由于数字 1 出如今咱们的 IN 列表中,而且咱们说“ NOT IN”…
如今,若是我要说这样的话怎么办?
SELECT * FROM SOME_TABLE
WHERE 5 NOT IN (1, 2, 3, 4, NULL)
复制代码
此 WHERE 子句将永远不会返回任何记录,由于它不是真正的可证实(它不能被证实是 true 的)。数字 5 没有明确出如今“ IN”列表中 - 可是 5 可能在咱们的“黑盒” NULL 值内(数据库不必定知道 NULL 的值是什么)。
这将产生 NULL 结果(表示未知结果),所以 WHERE 子句永远不会返回任何记录。
这就是为何将 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');
复制代码