Oracle SQL LEFT JOIN语法疑问:TABLE2与TABLE3连接及等价性确认
关于Oracle SQL中TABLE2与TABLE3连接方式及查询等价性的分析
针对你遇到的Oracle SQL语法疑问,我结合Oracle常见的特殊连接语法场景来拆解分析:
常见的Oracle特殊连接语法解析
Oracle除了支持ANSI标准的JOIN语法,还有传统的隐式连接写法,以及用(+)标识的外连接,这是最容易混淆的点:
若原查询是类似下面的传统写法:
SELECT t1.*, t2.*, t3.* FROM TABLE1 t1, TABLE2 t2, TABLE3 t3 WHERE t1.id = t2.id(+) AND t2.code = t3.code(+);这里
t2.id(+)表示TABLE1左外连接TABLE2,t3.code(+)表示TABLE2左外连接TABLE3,最终TABLE3中未匹配的行对应列会返回NULL。若你的“指定查询”是ANSI标准的外连接写法:
SELECT t1.*, t2.*, t3.* FROM TABLE1 t1 LEFT JOIN TABLE2 t2 ON t1.id = t2.id LEFT JOIN TABLE3 t3 ON t2.code = t3.code;这两个查询是完全等价的,逻辑一致,只是语法风格不同。
判断查询等价性的核心依据
要确认两个查询是否等价,重点看这两点:
- 连接类型完全匹配:内连接、左/右外连接的类型必须一致,Oracle的
(+)符号位置决定了外连接方向——比如a.col = b.col(+)是a左连b,a.col(+) = b.col是a右连b。 - 过滤条件的作用时机:注意
WHERE子句的过滤条件是否会改变连接结果,比如外连接后在WHERE中过滤从表的非空列,会把外连接转换成内连接,这时候和ANSI写法中把条件放在ON子句里的结果就完全不同。
举个反例,这两个查询就不等价:
原查询(传统写法):
SELECT * FROM TABLE1 t1, TABLE2 t2, TABLE3 t3 WHERE t1.id = t2.id(+) AND t3.code = t2.code AND t2.status = 'ACTIVE';
指定查询(ANSI写法):
SELECT * FROM TABLE1 t1 LEFT JOIN TABLE2 t2 ON t1.id = t2.id AND t2.status = 'ACTIVE' JOIN TABLE3 t3 ON t2.code = t3.code;
原因是原查询中WHERE的t2.status = 'ACTIVE'会过滤掉TABLE2中status为空的行(也就是TABLE1中未匹配TABLE2的行),而指定查询把条件放在ON子句里,会保留TABLE1中未匹配TABLE2的行,只是这些行的TABLE2列全为NULL。
内容的提问来源于stack exchange,提问作者Hana
相关产品推荐
相关产品推荐

