LEFT JOIN 右表无匹配时显示 NULL 是 SQL 标准行为,非 bug;常见误用是 WHERE 中过滤右表字段导致等效 INNER JOIN,正确做法是将条件移至 ON 子句。

LEFT JOIN 右表匹配不到时显示 NULL,是 SQL 标准定义的正常行为,不是 bug,也不是数据库连不上——你写了 LEFT JOIN,就注定会看到 NULL。
LEFT JOIN 的语义就是“左表全保留,右表没匹配就填 NULL”
SQL 明确规定:LEFT JOIN 必须让左表每一行都出现在结果中。右表若无满足 ON 条件的行,对应字段一律置为 NULL。
比如:
SELECT u.name, o.total FROM users u LEFT JOIN orders o ON u.id = o.user_id
当用户 ID 为 123 的人从未下单,o.total 就是 NULL——这恰恰说明 LEFT JOIN 正常工作了。
这不是“查不到”,而是“查到了,但右表确实没数据”。
为什么你看到的全是 NULL?大概率是 WHERE 干的
最常见误操作:在 WHERE 子句里对右表字段加条件,比如:
-
WHERE o.status = 'paid'—— 这会把所有o.status IS NULL的行(即没订单的用户)全部过滤掉 - 效果等同于
INNER JOIN,LEFT JOIN 形同虚设
正确做法是把筛选移到 ON:
LEFT JOIN orders o ON u.id = o.user_id AND o.status = 'paid'
这样左表行仍在,没匹配上的 o.* 字段还是 NULL,但整行不会丢。
匹配失败的真实原因往往藏在数据里
ON 条件不成立,LEFT JOIN 就只能填 NULL;它不会报错,也不会提醒你字段对不上。
-
NULL = anything永远返回UNKNOWN,不是TRUE,所以含NULL的连接键必然失败 - 类型不一致:如
users.id是INT,orders.user_id是VARCHAR且存了'123 '(带空格),隐式转换后比较失败 - 不可见字符:用
SELECT user_id, HEX(user_id) FROM orders WHERE user_id LIKE '%123%'查HEX结果,20是空格,09是制表符 - 避免在
ON里用函数(如UPPER()),索引失效,还可能因大小写规则导致匹配失败
想查“左表有、右表无”的记录,得用 WHERE 右表主键 IS NULL
这是唯一可靠的方式,但必须选对字段:
- ✅ 安全写法:
WHERE o.id IS NULL(o.id是右表主键,不可能非空) - ❌ 危险写法:
WHERE o.status IS NULL(业务允许status为空,会混入脏数据) - ❌ 错误写法:
WHERE o.id = NULL(= NULL永远不成立,必须用IS NULL)
真正难调试的,从来不是“为什么有 NULL”,而是“为什么没数据却看起来像有数据”——比如多层嵌套 LEFT JOIN 中某一层先因条件过严返回空集,外层只剩一堆 NULL,但你只看最终结果,根本看不出断在哪一环。










