首页/数据/SQL 速查/FULL OUTER JOIN 全外连接

FULL OUTER JOIN 全外连接

两边都保留、互不匹配的位置补 NULL:PostgreSQL 与标准 SQL 支持 FULL OUTER JOIN,MySQL 不支持,可用 LEFT/RIGHT 加 UNION 模拟。

SQL 速查数据更新于 2026-10-13

全外连接与模拟写法

全外连接把两侧都保留:左表独有的行、两侧匹配上的行、右表独有的行,全部出现在结果里,互不匹配的位置补空。PostgreSQL 与标准 SQL 直接支持这个语法,MySQL 不支持,只能拼出来——左侧保留一次、右侧保留一次,再合并去重。拼接时要特别小心去重方式:使用会去重的合并形式,匹配行确实只出现一次,但业务上本来就重复的行也会被合并掉。

基本信息

适用平台PostgreSQL 与非 MySQL 数据库支持;MySQL 8.0 不支持该语法
结果构成左表独有加匹配行加右表独有
MySQL 模拟保留左侧的结果与保留右侧的结果合并
去重注意用去重形式会顺带合并业务重复行
安全改写保留侧加过滤条件,把两次结果用不去重形式拼接

典型使用场景

  • 两张表双向比对:找出只在左侧、只在右侧以及两侧都有的数据
  • 数据迁移核验:源表与目标表逐键比对,确认没有漏迁或多迁
  • 对账差异定位:两边都缺的、单边多的分别列出
  • 配置同步检查:两边配置项的并集清单
  • 用户与权限关系核对:找出孤立记录

原语与 MySQL 模拟

原语与 MySQL 模拟
-- PostgreSQL:直接写全外连接
SELECT *
FROM a
FULL OUTER JOIN b ON a.k = b.k;

-- MySQL 模拟一:用会去重的合并,匹配行只出现一次
SELECT * FROM a LEFT JOIN b ON a.k = b.k
UNION
SELECT * FROM a RIGHT JOIN b ON a.k = b.k;

-- MySQL 模拟二:更安全,用不去重形式拼接两次结果
-- (把重复来源过滤掉,避免业务重复行被合并)
SELECT * FROM a LEFT JOIN b ON a.k = b.k
UNION ALL
SELECT * FROM a RIGHT JOIN b ON a.k = b.k WHERE a.k IS NULL;

-- 双向差异清单:只关心各自独有的行
-- 左独有:保留左侧结果中右表键为空的行
-- 右独有:保留右侧结果中左表键为空的行

两种模拟方式对比

模拟方式匹配行副作用
会去重的合并只出现一次业务上重复的行也被合并
不去重形式加过滤只出现一次不干扰业务重复行,改写更啰嗦
仅两次全保留再合并出现两次结果行数翻倍,需自行处理
单侧外连接结构不等价只能看一个方向,不能替代
全外连接结果里「匹配上的行」数量等于逻辑上两侧键交集的实际行数。用会去重的合并形式做两表核验时,如果任意一侧存在同一键的多行数据,交集部分会被去重成一到多行不等,核验结论就不可靠了。
只想知道「哪一侧多了数据」时,不必每次都拼全外连接:分别做一次外连接并筛出未匹配行,结果更直观,执行代价也更低。

易错点

  • 在 MySQL 里直接写全外连接会语法报错,必须改成两次外连接合并的写法
  • 用会去重的合并模拟时忽略业务重复行:交集部分的重复数据被合并,核验结论失真
  • 拼接两个分支时列顺序或列数不一致,语句报错或取值错位
  • 忘了处理匹配行在两次结果里重复出现的问题,最终行数比预期多
  • 在全外连接结果上直接做统计,把补空产生的行也算进业务口径

数据来源与参考

  • MySQL 8.0 Reference Manual · JOIN Clause(无 FULL JOIN)
  • PostgreSQL Documentation · FULL OUTER JOIN
​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌