SQL ANSI连接及其中的表顺序

时间:2011-09-28 13:53:01

标签: sql oracle

以下查询会自动从“旧”语法转换为ANSI语法,并出现错误:

select *    
  from ods_trf_pnb_stuf_lijst_adrsrt2 lst    
  join ods_stg_pnb_stuf_pers_adr pas    
    on (pas.soort_adres = lst.soort_adres)    
 right outer join ods_stg_pnb_stuf_pers_nat nat    
    on (prs.id = nat.prs_id)                     <<<prs.id invalid identifier
      join ods_stg_pnb_stuf_adr adr
        on (adr.id = pas.adr_id)
      join ods_stg_pnb_stuf_np prs
        on (prs.id = pas.prs_id)

我想这是因为在声明表之前引用了表prs。在查询中移动prs连接可以解决问题:

select *
  from ods_trf_pnb_stuf_lijst_adrsrt2 lst
  join ods_stg_pnb_stuf_pers_adr pas
    on (pas.soort_adres = lst.soort_adres)
  join ods_stg_pnb_stuf_np prs               <<< this first
    on (prs.id = pas.prs_id)
 right outer join ods_stg_pnb_stuf_pers_nat nat
    on (prs.id = nat.prs_id)                 <<< now prs.id is known
  join ods_stg_pnb_stuf_adr adr
    on (adr.id = pas.adr_id)
 where lst.persoonssoort = 'PERSOON'
   and pas.einddatumrelatie is null

有没有办法编写此查询,以便顺序限制较少,仍然使用ANSI语法?

4 个答案:

答案 0 :(得分:3)

除非先前已在联接列表中,否则您无法引用该表。这是正常和预期的行为。为什么这是个问题?

答案 1 :(得分:3)

如果破解的查询是由旧的非ANSI语法的工具生成的,则会生成工具损坏的代码。但是,无论from子句中的表的顺序如何,使用ANSI样式的连接都应该产生相同的结果。那是

select *
from      t1
join      t2 on t2.id = t1.id
left join t3 on t3.id = t1.id

将为您提供相同的结果(尽管结果集中列的顺序不同)为

select *
from      t1
left join t3 on t3.id = t1.id
join      t2 on t2.id = t1.id

请注意,from子句不能以破坏连接条件隐含的依赖关系的方式重新排序。但是,您也可以重新/重构from子句,以便以不同的方式表达查询,从而产生相同的结果集。例如,上面的查询等同于

select *
from       t3
right join t1 on t1.id = t3.id
join       t2 on t2.id = t1.id

答案 2 :(得分:0)

正常(“INNER”)JOIN

 SELECT ...
 FROM a
 JOIN b ON (a.x = b.y) 

相当于带有两个表的SELECT和一个适当的WHERE子句

SELECT ...
FROM a, b
WHERE a.x = b.y

对于左/右/外连接,您仍然受到“非对称”连接语法的限制。

答案 3 :(得分:0)

我认为最初的SQL代码应该是这样的,

select *
from  ods_trf_pnb_stuf_lijst_adrsrt2 lst
    , ods_stg_pnb_stuf_pers_adr pas
    , ods_stg_pnb_stuf_pers_nat nat
    , ods_stg_pnb_stuf_adr adr
    , ods_stg_pnb_stuf_np prs
where 
    pas.soort_adres = lst.soort_adres
and prs.id(+) = nat.prs_id
and adr.id = pas.adr_id
and prs.id = pas.prs_id
and lst.persoonssoort = 'PERSOON'
and pas.einddatumrelatie is null

ods_stg_pnb_stuf_np prs位于from子句的末尾,该子句在Oracle专有连接中有效, 但是当将其转换为ANSI SQL语法时,应该在引用之前先连接表prs。这是人们在将Oracle专有连接转换为ANSI SQL语法时所犯的常见错误。

将Oracle专有连接转换为ANSI SQL语法时还存在一些其他问题:

  1. 缺少额外的加入条件。
  2. 在将某些条件移入连接子句后,where子句中的条件被破坏。
  3. 如果您的同事需要将Oracle专有连接重写为ANSI SQL语法,则本文中列出的demos(both in java and C#)应该会有所帮助。