NULL:没有值
第 1 课里已经见过:有的客户没留邮箱,那一格显示 NULL。
1SELECT id, name, email2FROM customers;
| id | name | |
|---|---|---|
| 1 | 林晓 | [email protected] |
| 2 | 王磊 | [email protected] |
| 3 | 陈静 | NULL |
| 4 | 张伟 | [email protected] |
| 5 | 刘洋 | [email protected] |
| 6 | 赵敏 | NULL |
| 7 | 孙强 | [email protected] |
| 8 | 周婷 | [email protected] |
| 9 | 吴昊 | NULL |
| 10 | 郑雪 | [email protected] |
NULL 的意思是「没有值」或者「不知道」。它不是 0,也不是空的文字 '':0 是一个数,'' 是一段长度为 0 的文字,而 NULL 什么都不是。这一课讲怎么和它打交道。
找出 NULL:IS NULL
找没留邮箱的客户,要写 IS NULL:
1SELECT name, email2FROM customers3WHERE email IS NULL;
| name | |
|---|---|
| 陈静 | NULL |
| 赵敏 | NULL |
| 吴昊 | NULL |
反过来,IS NOT NULL 找有值的。员工表里,有上级的员工:
1SELECT name, manager_id2FROM employees3WHERE manager_id IS NOT NULL;
| name | manager_id |
|---|---|
| 马超 | 1 |
| 杨帆 | 1 |
| 黄磊 | 2 |
| 何琳 | 2 |
| 高远 | 3 |
1 号经理没有上级,他的 manager_id 是 NULL,所以不在结果里。
= NULL 什么也查不到
这是初学者最常踩的坑。
结果有几行?
1SELECT name2FROM customers3WHERE email = NULL;
email = NULL 不报错,可是对每一行都不成立,所以一行也查不到。找 NULL 要写 email IS NULL。
运行一下看看:
1SELECT name2FROM customers3WHERE email = NULL;
| name |
|---|
为什么?拿一个值和「不知道」比,结果也是「不知道」,不是「成立」。WHERE 只留下条件成立的行,「不知道」的行都被去掉了。就连 NULL = NULL 也是「不知道」:两个不知道的东西,没法说它们相等。
不等于也跳过 NULL
同样的道理,<> 也不会挑出 NULL 的行。邮箱不是 [email protected] 的客户,有几个?
10 个客户,去掉林晓,只剩 6 行,不是 9 行:3 个没邮箱的客户也不见了。和 NULL 比较不成立,不等于也不成立。要把它们也算进来,得明说:
1SELECT name, email2FROM customers3WHERE email <> '[email protected]' OR email IS NULL;
| name | |
|---|---|
| 王磊 | [email protected] |
| 陈静 | NULL |
| 张伟 | [email protected] |
| 刘洋 | [email protected] |
| 赵敏 | NULL |
| 孙强 | [email protected] |
| 周婷 | [email protected] |
| 吴昊 | NULL |
| 郑雪 | [email protected] |
NULL 参与计算
SELECT 也可以不写 FROM,直接算几个值。NULL 参与计算,结果还是 NULL;参与比较,结果也是 NULL(「不知道」):
1SELECT 10 + NULL, NULL * 2, NULL = NULL, NULL IS NULL;| 10 + NULL | NULL * 2 | NULL = NULL | NULL IS NULL |
|---|---|---|---|
| NULL | NULL | NULL | 1 |
只有 IS NULL 给出了确定的答案:1 表示成立(MySQL 用 1 表示成立,0 表示不成立)。
换成别的值:COALESCE
显示结果时,NULL 常常要换成一个看得懂的值。COALESCE(a, b):a 不是 NULL 就用 a,是 NULL 就用 b:
1SELECT name, COALESCE(email, '没留邮箱') AS email2FROM customers;
| name | |
|---|---|
| 林晓 | [email protected] |
| 王磊 | [email protected] |
| 陈静 | 没留邮箱 |
| 张伟 | [email protected] |
| 刘洋 | [email protected] |
| 赵敏 | 没留邮箱 |
| 孙强 | [email protected] |
| 周婷 | [email protected] |
| 吴昊 | 没留邮箱 |
| 郑雪 | [email protected] |
AS email 给这一列起个名字,不然列名就是一长串 COALESCE(email, '没留邮箱')。下一课细讲 AS。
COALESCE 可以写好几个值,用第一个不是 NULL 的。MySQL 还有一个只接两个值的 IFNULL(a, b);COALESCE 是标准写法,哪个数据库都能用。
NULL 排在哪
按有 NULL 的列排序,MySQL 把 NULL 当成最小的:升序排在最前,降序排在最后:
1SELECT name, email2FROM customers3ORDER BY email, id;
| name | |
|---|---|
| 陈静 | NULL |
| 赵敏 | NULL |
| 吴昊 | NULL |
| 林晓 | [email protected] |
| 王磊 | [email protected] |
| 张伟 | [email protected] |
| 刘洋 | [email protected] |
| 孙强 | [email protected] |
| 周婷 | [email protected] |
| 郑雪 | [email protected] |
3 个 NULL 的邮箱一样,所以再按 id 排,顺序才定得下来。别的数据库可能相反(PostgreSQL 和 Oracle 把 NULL 排在升序的最后)。
练一练
写好查询,点检查。提示随便看,实在想不出来再看答案。
修好它:和 NULL 比较
✓想查出有上级的员工,显示 name 和 manager_id,按 id 排,可是一行也查不到。改好它。
| name | manager_id |
|---|---|
| 马超 | 1 |
| 杨帆 | 1 |
| 黄磊 | 2 |
| 何琳 | 2 |
| 高远 | 3 |
1SELECT name, manager_id2FROM employees3WHERE manager_id <> NULL4ORDER BY id;
联系方式
✓查出上海的客户,显示 name 和 contact 两列:contact 是邮箱,没有邮箱的显示 无,按 id 排。
| name | contact |
|---|---|
| 林晓 | [email protected] |
| 陈静 | 无 |
| 周婷 | [email protected] |
1SELECT name, email2FROM customers3WHERE city = '上海';
这一课学会了
NULL是「没有值」,不是 0,也不是空的文字。- 找它用
IS NULL、IS NOT NULL;= NULL和<> NULL一行也查不到,也不报错。 - 和
NULL比较、计算,结果还是NULL;WHERE只留下条件成立的行,所以<>也会漏掉NULL的行。 COALESCE(a, b)把NULL换成别的值;MySQL 的IFNULL也行,但COALESCE哪儿都能用。- MySQL 排序时
NULL最小,别的数据库可能排在最后。