SQL 中判断数据是否为空(NULL)需要特别注意以下关键事项
在 SQL 中判断数据是否为空(NULL
)需要特别注意以下关键事项,这些是实际开发中最常见的陷阱:
⚠️ 核心注意事项
1. 必须使用 IS NULL
/ IS NOT NULL
-- ✅ 正确写法
SELECT * FROM users WHERE phone IS NULL; -- 查空值
SELECT * FROM users WHERE phone IS NOT NULL; -- 查非空
-- ❌ 致命错误写法(永远无效!)
SELECT * FROM users WHERE phone = NULL; -- 错误!
SELECT * FROM users WHERE phone != NULL; -- 错误!
原因:
NULL
代表 未知值/缺失值,在 SQL 逻辑中:
-
NULL = NULL
→ 结果不是TRUE
而是UNKNOWN
- 任何与
NULL
的比较都返回UNKNOWN
-
WHERE
子句只返回条件为TRUE
的行(过滤掉UNKNOWN
)
2. 聚合函数忽略 NULL 值
SELECT
COUNT(phone) AS not_null_count, -- 只统计非空值
COUNT(*) AS total_rows -- 统计所有行(含NULL)
FROM users;
-
AVG()
、SUM()
等聚合函数 自动跳过NULL
- 例外:
COUNT(*)
统计所有行(包括NULL
值行)
3. 算术运算中的 NULL 污染
SELECT 10 + NULL; -- 结果 → NULL
SELECT 100 / NULL; -- 结果 → NULL
任何包含 NULL
的算术运算结果都是 NULL
4. 逻辑运算的特殊性
SELECT NULL AND TRUE; -- 结果 → NULL
SELECT NULL OR FALSE; -- 结果 → NULL
SELECT NOT NULL; -- 结果 → NULL
- 三值逻辑:
TRUE
/FALSE
/UNKNOWN
(NULL
参与时可能返回UNKNOWN
)
🧩 空字符串 vs NULL 的区别
特性 | NULL |
'' (空字符串) |
---|---|---|
数据类型 | 表示"未知" | 有效的字符串值 |
存储占用 | 无数据存储 | 占用存储空间(长度0) |
比较结果 |
NULL = NULL → 未知 |
'' = '' → TRUE
|
查询方式 | WHERE col IS NULL |
WHERE col = '' |
示例:
INSERT INTO test VALUES (NULL), ('');
-- 区分查询:
SELECT * FROM test WHERE col IS NULL; -- 只返回 NULL
SELECT * FROM test WHERE col = ''; -- 只返回空字符串
🛠️ 处理 NULL 的最佳实践
1. 使用安全函数
-- 将 NULL 转为默认值
SELECT COALESCE(phone, 'N/A') FROM users; -- NULL → 'N/A'
-- 条件判断(类似三元表达式)
SELECT IFNULL(phone, '未填写') FROM users; -- MySQL
SELECT NVL(phone, '未知') FROM employees; -- Oracle
2. 空值检查综合方案
-- 同时检测 NULL 和空字符串
SELECT * FROM products
WHERE COALESCE(description, '') = '';
-- 或使用
WHERE description IS NULL OR description = '';
3. 索引优化建议
- 对频繁查询的列使用
NOT NULL
约束(可提升索引效率) - 避免在可空列上建立唯一索引(因唯一索引允许多个
NULL
)
⚡ 开发中常见陷阱
陷阱1:NOT IN 子查询包含 NULL
-- 错误示例(返回空结果)
SELECT * FROM orders
WHERE customer_id NOT IN (
SELECT id FROM customers WHERE status = 'inactive' -- 子查询可能含 NULL
);
✅ 修正方案:
SELECT * FROM orders
WHERE customer_id NOT IN (
SELECT id FROM customers
WHERE status = 'inactive'
AND id IS NOT NULL -- 显式排除 NULL
);
陷阱2:连接查询的 NULL 匹配
-- 内连接会过滤掉 NULL 关联的行
SELECT *
FROM employees e
JOIN departments d ON e.dept_id = d.id; -- dept_id 为 NULL 的员工不会出现
✅ 解决方案:
-- 使用左连接保留 NULL 关联行
SELECT *
FROM employees e
LEFT JOIN departments d ON e.dept_id = d.id;
💡 设计建议
-
表设计时:
- 明确列是否允许
NULL
(用NOT NULL
约束强制非空) - 为重要字段设置默认值(如
DEFAULT ''
或DEFAULT 0
)
- 明确列是否允许
-
查询时:
- 永远用
IS NULL
判断空值 - 对可空列做运算时先用
COALESCE
转换
- 永远用
-
业务逻辑:
- 区分
NULL
(未设置)和空字符串(用户主动清空)的业务含义
- 区分
上一篇: 几秒钟就充满电!科学
下一篇: 暂无数据