我遇到了以下遗留的PL / SQL,并且发现针对标量常量的外连接有些令人困惑。首先,有人可以确认我将此转换为ANSI的尝试是正确的。
遗产代码:
cursor c1item (c1item_iel_id number) is
select
`<columns>`
from iel_item iit, iel_item_property iip
where iit.iit_change_type = 'I'
and iip.iip_change_type (+) = 'I'
and iip.it_id (+) = iit.it_id
and iit.iel_id = c1item_iel_id
and iip.iel_id (+) = c1item_iel_id;
ANSI CODE
cursor c1item (c1item_iel_id number) is
select
`<columns>`
from iel_item iit
left outer join iel_item_property iip
on iip.it_id = iit.it_id
and iit.iit_change_type = 'I'
and iip.iip_change_type = 'I'
and iit.iel_id = c1item_iel_id
and iip.iel_id = c1item_iel_id;
如果这是正确的,那么我没有看到使用外连接的意义。当然,如果表 iit 中的主键 it_id 在表 iip 中没有相应的外键,那么 iip.iit_change_type 和 iip.iel_id 将为NULL,在这种情况下,它们将被AND子句过滤掉。那么为什么不使用内连接呢?我错过了什么吗?或原始代码是废话?
答案 0 :(得分:6)
不,它不正确 - 只有标有“(+)”的那些需要在LEFT JOIN中,其余的都是WHERE子句:
SELECT `<columns>`
FROM iel_item iit
LEFT JOIN iel_item_property iip ON iip.it_id = iit.it_id
AND iip.iip_change_type = 'I'
AND iip.iel_id = c1item_iel_id
WHERE iit.iit_change_type = 'I'
AND iit.iel_id = c1item_iel_id
放置与OUTER JOIN有关 - ON子句中的条件在JOIN之前应用,而WHERE中的条件在JOIN之后应用 。这可能会极大地影响返回的结果集,具体取决于数据和设置。对于INNER JOINS,放置无关紧要 - 在WHERE或ON子句中,结果集将是相同的。
答案 1 :(得分:3)
不,这不对。原始查询中只有3个外连接谓词,新的谓词全部为5。
应该是:
cursor c1item (c1item_iel_id number) is
select
`<columns>`
from iel_item iit
left outer join iel_item_property iip
on iip.it_id = iit.it_id
and iip.iip_change_type = 'I'
and iip.iel_id = c1item_iel_id
where and iit.iel_id = c1item_iel_id
and iit.iit_change_type = 'I' ;
答案 2 :(得分:0)
它也可以像这样重写:
SELECT columns1
FROM iel_item iit
RIGHT OUTER JOIN iel_item_property iip
ON iip.iip_change_type = 'I'
AND iip.it_id = iit.it_id
AND iip.iel_id = c1item_iel_id
WHERE iit.iit_change_type = 'I'
AND iit.iel_id = c1item_iel_id
下次,如果您需要将Oracle专有连接重写为符合ANSI SQL的连接,here is a tool可以帮助您自动执行此操作,并且不易出错。