开发者

Conversion of legacy outer join to ANSI

I have come across the following legacy PL/SQL and find the outer joins against scalar constants somewhat confusing. First of all, can someone please confirm that my attempt to convert this to ANSI is correct.

LEGACY CODE:

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;

If this is correct, then I don't see the point of using an outer join. Surely if the primary key it_id in table iit does not ha开发者_C百科ve a corresponding foreign key in table iip then both iip.iit_change_type and iip.iel_id will be NULL, in which case they will be filtered out by the AND clauses. So why not just use an inner join? Am I missing something? or is the original code nonsense?


No, it's not correct -- only those marked with the "(+)" need to be in the LEFT JOIN, the rest are for the WHERE clause:

   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  

Placement matters with OUTER JOINs -- criteria in the ON clause is applied before the JOIN, while criteria in the WHERE is applied after the JOIN. This can greatly affect the result set returned, depends on data and setup. Placement doesn't matter for INNER JOINS - in the WHERE or ON clause, the result set will be the same.


No it isn't correct. There were only 3 outer join predicates in the original query, your new one has all 5.

Should be:

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' ; 


It can also be rewrited like this:

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

Next time, if you need to rewrite Oracle proprietary joins to ANSI SQL compliant joins, here is a tool that can help you do it automatically with less error prone.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜