Oracle旧版(+)连接语法转ANSI JOIN的正确实现方案咨询
Oracle老式(+)外连接转ANSI JOIN标准语法指南
转换核心原理
- Oracle的
(+)是老式外连接语法,(+)标注在哪一侧的表列上,哪一侧就是可选表,另一侧为保留表,对应ANSI语法的左/右外连接:- 条件格式
保留表.列 = 可选表.列 (+),等价于保留表 LEFT OUTER JOIN 可选表 ON 保留表.列 = 可选表.列
- 条件格式
- 多表关联的过滤条件如果涉及可选表的列,必须放到对应JOIN的
ON子句中,放到WHERE子句会过滤掉可选表为NULL的行,等效为内连接 - 多表关联顺序需要和
(+)的依赖关系保持一致,避免关联条件匹配逻辑错位
原SQL逻辑分析
原Oracle SQL代码如下:
SELECT * FROM a, b, c WHERE b.id (+) = a.id1 AND b.xxx = c.yyy AND c.id (+) = a.id2
原SQL的逻辑为:
- 表A是唯一的全量保留表,B、C均为可选关联表,A的所有行都会出现在结果中
- 关联规则:
- 用A的id1匹配B的id,匹配不上时B的所有字段为NULL
- 用A的id2匹配C的id,同时要求匹配到的B的xxx字段等于C的yyy字段,匹配不上时C的所有字段为NULL
两种写法正误判定
正确写法:写法1
select * from A left outer join B on B.ID = A.ID1 left outer join C on C.ID = A.ID2 AND B.xxx = C.yyy
正确性说明:
关联顺序和原逻辑完全匹配,先完成A和B的左关联,再将关联结果和C做左关联,B.xxx = C.yyy作为C表关联的匹配条件,完全复现原SQL的过滤逻辑。
错误写法:写法2
select * from A left outer join C on C.ID = A.ID2 left outer join B on B.ID = A.ID1 AND B.xxx = C.yyy
错误原因:
先关联C再关联B时,B.xxx = C.yyy变成了B表的关联条件,当C的匹配结果为NULL时,会导致原本能匹配到的B行被过滤,和原SQL的逻辑不一致,返回结果集比原SQL少。
内容的提问来源于stack exchange,提问作者kilzaprt
相关产品推荐
相关产品推荐

