在维护老系统时,可能会看到一些使用(+)运算符的SQL查询。这种语法是Oracle专有的连接语法,常用于实现左连接或右连接。这里有一个核心细节:用(+)实现右连接时,必须把(+)加在等号左侧的列上,并且整个查询要使用旧式的逗号语法(隐式连接)。如果混用了JOIN关键字,或者漏掉了某个条件的(+),都
Oracle SQL旧式右连接:(+)语法详解
时间:2026-06-18
浏览:549
文章目录
在维护老系统时,可能会看到一些使用(+)运算符的SQL查询。这种语法是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关键字,再加(+),Oracle解析器会直接报错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子句中涉及多个表间的关联条件,务必在每个条件的“从表列”上加(+)。否则,整个外连接的逻辑都会失效,可能会退化为内连接。
- 假设要连接
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+环境下的兼容性陷阱
虽然(+)语法在Oracle 12c及之后的版本仍然能运行,但官方已经明确标注它为“deprecated”。在复杂查询(比如带有子查询、WITH子句、分析函数)中,它更容易触发解析异常或执行计划偏差。在实际迁移时,最常踩的坑不是语法错误,而是(+)和AND条件顺序导致的过滤提前。例如,把AND emp.sal > 2000写在(+)条件的后面,会导致Oracle先过滤数据再进行外连接,结果和预期完全不同。
真正难处理的是混合场景:老系统中的SQL嵌套深、别名多,再加上ORDER BY子句,此时(+)的作用域边界会变得非常模糊。与其在这种环境里纠结,不如直接把它重写为RIGHT JOIN来得更可控。
实用工具推荐
绿化、压缩、噪点和虚拟水印,自由调节做旧程度。
选择画质和输出格式,预览压缩前后的大小。