因为null是缺失标记而非值,col = null恒返回unknown,而where只保留true行。

WHERE 中写 col = NULL 为什么永远查不到数据
因为 NULL 不是值,而是“缺失标记”,它不参与任何等值比较。col = NULL 的结果恒为 UNKNOWN,而 WHERE 只保留 TRUE 行,UNKNOWN 和 FALSE 都被过滤掉。
常见错误现象:LEFT JOIN 后想筛选右表没匹配上的行,却写成 WHERE right_table.id = NULL,结果返回空集。
- 正确写法必须是
WHERE right_table.id IS NULL - 如果要同时查“匹配上的 + 没匹配上的”,不能用
IN包含 NULL:WHERE right_table.status IN ('A', 'B', NULL)等价于WHERE right_table.status IN ('A', 'B'),最后一项失效 - 得拆开写:
WHERE right_table.status IN ('A', 'B') OR right_table.status IS NULL
LEFT JOIN 后右表字段为 NULL,该用 ISNULL 还是 COALESCE 填充
优先用 COALESCE,尤其在跨库或视图场景中。它支持多参数、类型推导更可预期,且是 ANSI 标准函数——SQL Server、PostgreSQL、MySQL、Oracle 全都认。
常见错误现象:ISNULL(right_table.name, 'N/A') 在右表 name 是 VARCHAR(10) 时,返回值也被截成 VARCHAR(10),若默认值超长就静默截断;而 COALESCE(right_table.name, 'N/A') 会按参数中最大长度推导(如 VARCHAR(20)),但前提是类型兼容。
- 数值列推荐:
COALESCE(right_table.amount, 0.00),避免ISNULL(amount, 0)把DECIMAL强转成INT - 字符串列若需控制长度,显式
CAST:COALESCE(CAST(right_table.name AS VARCHAR(100)), 'N/A') - 不要在
COALESCE里混日期和字符串:COALESCE(modified_date, '1900-01-01')在 PostgreSQL 会报错,应写成COALESCE(modified_date, CAST('1900-01-01' AS DATETIME2))
JOIN 条件里能用 ISNULL 或 COALESCE 吗
能写,但强烈不建议。这类函数会破坏索引使用,让 JOIN 变成全表扫描。
例如:ON ISNULL(left.status, 'active') = ISNULL(right.status, 'active'),数据库无法利用 status 字段上的索引,即使表只有几万行,性能也可能骤降。
- 真正需要“空值也视为相等”的语义,应改用
OR (left.status IS NULL AND right.status IS NULL)配合非空等值判断 - 更清晰的写法是:
ON left.status = right.status OR (left.status IS NULL AND right.status IS NULL) - 如果只是想补默认值再比,说明设计已有隐患——关联字段本不该允许 NULL,应优先考虑约束或 ETL 清洗
COALESCE 能处理空字符串或 0 这类“假空”吗
不能。COALESCE 只识别 SQL 意义上的 NULL,对空字符串 ''、数字 0、空白串 ' ' 都无感。
常见翻车场景:用户昵称字段存了 '',COALESCE(nickname, '游客') 仍返回空字符串,不是预期的“游客”。
- 要统一处理 NULL 和空字符串,得套
NULLIF:COALESCE(NULLIF(TRIM(nickname), ''), '游客') - 想把 0 也当空处理?加一层逻辑:
COALESCE(NULLIF(NULLIF(TRIM(nickname), ''), '0'), '游客'),但注意这会让语义变重,建议先在业务层归一化 - 所有这类“假空”清洗,最好放在 ETL 或 INSERT/UPDATE 触发器里,而不是每次查询都算一遍
COALESCE 盖住,可能把数据质量问题拖进报表和模型里。










