Conversion of legacy outer join to ANSI

↘锁芯ラ 提交于 2019-12-24 22:34:32

问题


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 have 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?


回答1:


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.




回答2:


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



回答3:


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.



来源:https://stackoverflow.com/questions/4796778/conversion-of-legacy-outer-join-to-ansi

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!