mysql 不支持 full outer join,因其官方明确不实现;需用 left join 加 not exists 与 union all 拼接右表独有数据,并注意 null 处理、字段对齐及类型声明。

MySQL 压根没实现 FULL OUTER JOIN,不是你语法写错,是它根本不认识这个词——执行就报 ERROR 1064。
为什么直接写 FULL JOIN 会报错
MySQL 解析器在语法层面就拒绝识别 FULL JOIN 或 FULL OUTER JOIN。这不是版本问题(8.0.32 仍不支持),也不是配置开关能打开的,而是官方明确不实现。原因很实际:
- 标准 SQL 中它存在,但 MySQL 团队认为使用频次低、执行开销高(需全表扫描 + 大量 NULL 填充)
- 多数业务场景可用
LEFT JOIN+ 应用层补漏替代,没必要内置复杂逻辑 - “UNION JOIN”这种写法也不存在——那是把两个词硬凑出来的幻觉,MySQL 会直接报错
用 UNION ALL 拼 LEFT JOIN 和 “右表独有” 查询最可靠
别用 LEFT JOIN + RIGHT JOIN 直接 UNION,那会因去重丢失真实重复行,且交集部分被算两次。正确拆法是:
- 第一段:
SELECT e.id, e.name, d.id AS dept_id, d.name AS dept_name FROM employees e LEFT JOIN departments d ON e.department_id = d.id - 第二段:只查“右表有、左表无”的记录,用
NOT EXISTS而非NOT IN,避免字段含NULL时整个子查询失效 - 必须用
UNION ALL,否则大表上UNION的排序+去重会拖慢几倍
示例中第二段要显式写成:SELECT NULL AS id, NULL AS name, d.id AS dept_id, d.name AS dept_name FROM departments d WHERE NOT EXISTS (SELECT 1 FROM employees e WHERE e.department_id = d.id)
字段对齐和类型声明最容易翻车
UNION ALL 对列结构极其敏感,稍不注意就触发 ERROR 1222:
- 左右两段 SELECT 的列数必须一致,顺序必须一致,同位置字段语义要对得上
-
NULL没有默认类型,如果左段是VARCHAR,右段只写NULL,MySQL 可能推成DECIMAL导致类型冲突 - 务必显式加别名,比如
NULL AS name或CAST(NULL AS CHAR),让类型可预期 - 所有字段都用别名统一名字,否则结果集列头混乱,下游取值容易错位
当连接字段本身允许为 NULL 时,NOT EXISTS 也会失效
这是最隐蔽的坑:如果 employees.department_id 允许为 NULL,那么 WHERE e.department_id = d.id 在子查询里永远不成立(NULL = anything 为 UNKNOWN),导致“右表独有”部分整块漏掉。
这时不能靠改写 ON 条件解决,得提前清洗数据,或改用 COALESCE(e.department_id, -1) = COALESCE(d.id, -1) 这类技巧兜底——但要注意 -1 是否在业务中真实存在。
真正麻烦的从来不是怎么写,而是你得先确认连接字段有没有 NULL、是否允许为空、以及空值在业务中代表什么含义。











