如何从旧的Oracle连接类型转换为ANSI连接,为什么?
SELECT *
FROM a, b, c
WHERE b.id (+) = a.id1
AND b.xxx = c.yyy
AND c.id (+) = a.id2
--应该是这个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
--或者这两个?
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
4条答案
按热度按时间30byixjq1#
您还可以使用Oracle SQL Developer进行“作弊”。
粘贴ANSI SQL查询或Oracle SQL查询,选择它,右键单击,然后使用转换功能。
SQL解析器将为您重写JOINS。
因此,这适用于任何查询,而不仅仅是您的问题/场景中的查询。
当然,您应该检查查询返回的执行计划和数据,以确保它们在功能上是等效的。
xcitsw882#
根据Oracle documentation:
如果WHERE子句包含将表B中的列与常数进行比较的条件,则必须对该列应用(+)运算符,以便Oracle返回表A中已为该列生成空值的行。否则,Oracle仅返回简单联接的结果。
因此,
b
和c
之间存在一个内连接。由于整体条件,这将把所有连接都转换为INNER JOIN
(b
和c
中需要有有效值才能使该条件生效。我认为相应的逻辑是:
也就是说,简单的相等消除将外联接转换为内联接。
当然,你可以测试这个。
oknwwptz3#
两个选项都没有:
将写成:
以及:
将写成:
你所拥有的是:
为甚么?
该行:
要求有一个
b
和一个c
行;当存在左外连接时,这将不会发生,因此该连接等同于内连接,并且查询可被重写为:这样就很清楚所有的联接都是内联接。
你可能想写的是:
即:
或者,在联接中使用括号设置联接的优先级:
pu3pd22g4#
如果运行simple
explain plan
并检查结果,您可能会看到它生成了两个inner join
:一个一个