2012-09-17 15 views
1

這個查詢:甲骨文外連接沒有給預期的效果(表現得像內部連接)

select * 
from table_a 
, table_b 
where table_a.id = table_b.id(+) 
    and table_b.name = 'BENEFICIARY' 

返回我沒有記錄。 table_b沒有名稱爲'BENEFICIARY'的記錄。但是無論如何,外連接都應該返回table_a中的所有記錄。沒有? 下面的查詢將返回表-A記錄預期:

select * 
from table_a 
, (select * 
    from table_b 
    where table_b.name = 'BENEFICIARY') AS table_b1 
where table_a.id = table_b1.id(+) 

爲什麼第一個查詢沒有返回記錄?

+0

爲什麼過時的語法?爲什麼不使用(ANSI符合!)「左/右連接」語法?????? – paulsm4

+2

如果你使用'(+)'語法(我個人喜歡,因爲ANSI語法是冗長的),那麼第5行應該是'table_b.name(+)='BENEFICIARY'。 –

回答

1

在第一個查詢中,過濾器正在被應用到結果中,在加入之後。

嘗試

select * 
from table_a 
    left join table_b 
    on table_a.id=table_b.id 
    and table_b.name='BENEFICIARY' 
+0

謝謝。但是,如何使用ANSI語法改變連接之後應用過濾器的事實? – Victor

+1

它沒有。上面的查詢沒有位置,所以過濾是在連接上完成的 – podiluska

4

舊式語法查詢

select * 
from table_a 
    , table_b 
where table_a.id = table_b.id(+) 
    and table_b.name = 'BENEFICIARY' 

是相同的ANSI查詢

select * 
from table_a 
     left outer join table_b on (table_a.id = table_b.id) 
where table_b.name = 'BENEFICIARY' 

在這兩種情況下,謂語table_b.name = 'BENEFICIARY'是後加入應用,而不是作爲連接的一部分,這打破了外部連接的目的。爲了確保該謂語爲連接操作的一部分,使用舊的語法,你需要

select * 
from table_a 
    , table_b 
where table_a.id = table_b.id(+) 
    and table_b.name(+) = 'BENEFICIARY' 

而與ANSI語法,你想

select * 
from table_a 
     left outer join table_b on ( table_a.id = table_b.id 
            and table_b.name = 'BENEFICIARY') 

一般來說,如果你」重新使用舊的語法,任何你想成爲連接條件的一部分的謂詞,而不是在連接之外應用的謂詞,需要將(+)運算符應用於它。同樣,當您使用ANSI語法時,您希望成爲連接條件一部分的謂詞需要成爲ON子句的一部分。

在這種情況下,ANSI語法除了更具可移植性之外,可能更易於理解,因此它通常是首選。