Oracle中(+)实现右连接需将(+)加在等号左侧列且必须用逗号语法;a.id(+)=b.id表示b表全保留、a表匹配补NULL,为右连接;混用JOIN或漏加(+)会导致错误或逻辑异常。
直接结论:在 Oracle 中用 (+) 实现右连接,必须把 (+) 加在等号左侧的列上,且整个查询必须使用旧式逗号语法(隐式连接),不能混用 JOIN 关键字。
(+) 放左边才是右连接?Oracle 的 (+) 本质是“补全”标记:它所在一侧的表是被限制匹配的表,另一侧的表则被“无条件保留”。所以 a.id(+)=b.id 表示:b 表的所有行都要出现,a 表只取能匹配 b.id 的行,不匹配的填 NULL —— 这就是右连接语义。
a.id = b.id(+) → 左连接(a 全部保留)a.id(+) = b.id → 右连接(b 全部保留)a.id(+) = b.id(+) → 语法错误,(+) 不能同时出现在两边JOIN
(+) 是 Oracle 9i 之前遗留的专有语法,和标准 LEFT JOIN、RIGHT JOIN 完全不兼容。一旦用了 JOIN 关键字,再加 (+) 会报错 ORA-00905: missing keyword 或直接解析失败。
SELECT * FROM emp, dept WHERE emp.deptno(+) = dept.deptno
SELECT * FROM emp RIGHT JOIN dept ON emp.deptno(+) = dept.deptno
SELECT * FROM emp, dept WHERE emp.deptno(+) = dept.deptno AND emp.ename LIKE '%A%'(漏了 (+),WHERE 中所有关联条件都得带)(+) 必须全覆盖如果 WHERE 中有多个表间关联条件,每个条件的“从表列”都得加 (+),否则逻辑失效,可能退化为内连接。
emp、dept、loc 三张表,且想让 loc 全部保留:WHERE dept.loc = loc.loc_id(+) AND emp.deptno = dept.deptno(+)
WHERE dept.loc = loc.loc_id(+) AND emp.deptno = dept.deptno(dept 不再被外连接,loc 的补全效果丢失)(+) 不能用于表达式,如 UPPER(emp.ename)(+) = 'SMITH' 会报错 ORA-00920: invalid relational operator
虽然 (+) 在 12c 及以后版本仍能运行,但官方已明确标注为“deprecated”,且在复杂查询(含子查询、WITH、分析函数)中更容易触发解析异常或执行计划偏差。实际迁移时最常踩的坑不是语法错,而是 (+) 和 AND 条件顺序导致过滤提前 —— 比如把 AND emp.sal > 2000 写在 (+) 条件后面,会先过滤再外连接,结果和预期不符。
真正难处理的是混合场景:老系统 SQL 嵌套深、别名多、又带 ORDER BY 子句,此时 (+) 的作用域边界模糊,不如直接重写为 RIGHT JOIN 更可控。