最轻量、最常用的方法是用 EXISTS 配合 IS NULL,它不扫描全表,找到第一个空值就返回 TRUE,适合大表快速探查:SELECT EXISTS(SELECT 1 FROM users WHERE email IS NULL);

用 SELECT EXISTS 快速判断某列是否含空值
最轻量、最常用的方法是用 EXISTS 配合 IS NULL,它不扫描全表,找到第一个空值就返回 TRUE,适合大表快速探查:
-
SELECT EXISTS(SELECT 1 FROM users WHERE email IS NULL);—— 返回t或f - 别写
SELECT COUNT(*) > 0,它会强制扫完所有匹配行,性能差很多 - 如果列有索引且为空值比例极低,
EXISTS可能走索引(但注意:普通 B-tree 索引默认不存NULL,需配合WHERE col IS NULL的部分索引或使用COALESCE伪索引技巧)
检查多列或整行是否全为空
业务中常需确认「关键字段是否集体缺失」,比如 name 和 phone 同时为空,这时不能简单用 OR,否则逻辑易错:
- 查「任一列为空」:
WHERE name IS NULL OR phone IS NULL - 查「全部列为空」:
WHERE name IS NULL AND phone IS NULL(注意不是name = NULL AND phone = NULL,= NULL永远返回NULL) - 查「整行无任何非空值」(罕见但存在):PostgreSQL 不支持
row IS NULL,得写成WHERE (col1, col2, col3) IS NOT DISTINCT FROM (NULL, NULL, NULL),但性能差,建议只在小表用
用 pg_stats 查统计信息预判空值率
如果只是想快速估算空值比例,不想执行查询,可直接查系统视图 —— 这对分析慢查询或设计 ETL 校验很有用:
SELECT null_frac FROM pg_stats WHERE tablename = 'orders' AND attname = 'discount';- 该值来自
ANALYZE,不一定实时;若近期没执行过ANALYZE,结果可能严重滞后 -
null_frac = 0.0不代表绝对没有空值,只说明采样中没发现;null_frac = 1.0才基本确定全为空
避免 NOT NULL 约束误判的陷阱
看到表结构里写了 email VARCHAR NOT NULL,不代表数据就真没空值 —— 可能约束是后来加的,旧数据未清理:
- 用
\d+ table_name在 psql 里看约束定义,但不等于数据合规 - 真正验证必须查数据:
SELECT ctid FROM users WHERE email IS NULL LIMIT 1;(ctid查得快,且能定位物理位置) - 如果发现空值而约束存在,说明约束是
NOT VALID状态,需用ALTER TABLE ... VALIDATE CONSTRAINT触发校验
空值检查看着简单,但实际要分清「语法层面是否存在」「统计层面是否大概率存在」「约束层面是否被强制阻止」—— 三者不等价,选错方法容易白忙活。










