SQL ANSI联接及其表的顺序

SQL ANSI联接及其表的顺序,sql,oracle,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.pr

以下查询将自动从旧语法转换为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语法?

普通的内部联接

 SELECT ...
 FROM a
 JOIN b ON (a.x = b.y) 
相当于包含两个表和一个appropiate WHERE子句的SELECT

SELECT ...
FROM a, b
WHERE a.x = b.y
对于左/右/外部联接,您仍然受到不对称联接语法的限制。

正常的内部联接

 SELECT ...
 FROM a
 JOIN b ON (a.x = b.y) 
相当于包含两个表和一个appropiate WHERE子句的SELECT

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

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

您无法引用表,除非它已在联接列表中。这是正常和预期的行为。为什么这是一个问题

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

如果断开的查询是由工具根据旧的非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

如果断开的查询是由工具根据旧的非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

我认为原始的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语法时还存在一些其他问题:

缺少附加的联接条件。 where子句中的条件在将某些条件移动到join子句后被破坏。
如果您的同事需要将Oracle专有连接重写为ANSI SQL语法,本文中列出的内容应该会有所帮助。

我认为原始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语法时还存在一些其他问题:

缺少附加的联接条件。 where子句中的条件在将某些条件移动到join子句后被破坏。
如果您的同事需要将Oracle专有连接重写为ANSI SQL语法,本文中列出的内容应该会有所帮助。

如果您需要在使用ANSI语法连接表之前引用表,那么您的查询逻辑可能是错误的。具有显式联接的查询强制您按照查询的顺序联接表。为什么要这样做?你是说你的固定版本没有正确的语义?如果是这样的话,请告诉我们所需的语义是什么。顺便说一句:它应该拼写为persoonsoort,加上one's:-这个问题的原因是我们有一个存储查询定义并生成查询的系统。有人重写了它,因此它现在使用ANSI语法。所以我有一个带有连接条件的表。每个记录都是一个条件。这些必须组合在一起构成一个查询。显然,这些连接条件在查询中的放置顺序很重要。@wildplasser:谢谢您指出这一点,但这是我目前最不关心的问题。如果您需要在使用ANSI语法连接表之前引用它,那么您的查询逻辑可能是错误的。具有显式联接的查询强制您按照查询的顺序联接表。为什么要这样做?你是说你的固定版本没有
“你没有正确的语义吗?如果是这样的话,请告诉我们所需的语义是什么。顺便说一句:它应该拼写为persoonsoort,加上one's:-这个问题的原因是我们有一个存储查询定义并生成查询的系统。有人重写了它,因此它现在使用ANSI语法。所以我有一个带有连接条件的表。每个记录都是一个条件。这些必须组合在一起构成一个查询。显然,这些连接条件在查询中的放置顺序很重要。@wildplasser:谢谢你指出这一点,但这是我目前最不关心的问题。