2017-02-01 53 views
5

Podczas konwersji niektórych łączeń w starym stylu do stylu SQL-92 przypadkowo pozostawiono w zapytaniu (+). Nie zgłoszono żadnego błędu, gdy spodziewałem się błędu: ORA-25156: starego stylu łączenia zewnętrznego (+) nie można używać z ANSI łączy do podniesienia.Nie można uzyskać "starego stylu łączenia zewnętrznego" (+) ORA-25156 "nie można używać z łączeniem ANSI", gdy powinienem być

I mają następujące tabele:

create table inner_join ( 
    id integer 
, some_data varchar2(32) 
    ); 

insert into inner_join values (1, 'a'); 
insert into inner_join values (2, 'b'); 

create table outer_join ( 
    id integer 
, some_data varchar2(32) 
    ); 

insert into outer_join values(2, 'c'); 
insert into outer_join values(3, 'd'); 

A (bardziej skomplikowany) zapytanie jak poniżej był przekształcany

select * 
    from outer_join oj 
    , inner_join ij 
where ij.id = oj.id(+); 

i omyłkowo zapytanie przeprowadzono następująco

select * 
    from outer_join oj 
    join inner_join ij 
    on ij.id = oj.id(+); 

Daje to oczekiwane wyniki, jednak jest dość niebezpieczne, ponieważ:

  • Łatwo ktoś przypuszczać, że INNER JOIN w przeciwieństwie do sprzężenia zewnętrznego został przeznaczony (zgadnij co się stało ...) powodując niezamierzone błędy, gdy kwerenda jest ponownie zmienił
  • Prezentowany zachowanie może się zmienić w przyszłości, w wyniku błędów w wielu miejscach
  • wydaje contradict the documentation

    nie można określić (+) operator w bloku zapytań, który zawiera również dołączyć klauzuli FROM składni.

  • Istotną korzyścią z wykorzystaniem standardu SQL-92 jest to, że gdy pojawi się błąd w kodzie (czyli brakuje warunku złączenia) nie będzie błędu

zawsze będę jak ORA -25156 do podniesienia, kiedy powinno być.

Aby zademonstrować ten problem: nie pojawia się błąd, gdy mam gdybym uruchomić te pytania

select * 
    from outer_join oj 
    join inner_join ij 
    on ij.id = oj.id(+); 

ID SOME_DATA ID SOME_DATA 
--- --------- --- --------- 
    2 c   2 b 
       1 a 


select * 
    from inner_join ij 
    join outer_join oj 
    on ij.id = oj.id(+); 

ID SOME_DATA ID SOME_DATA 
--- --------- --- --------- 
    2 b   2 c 
    1 a 

Jeśli dodać trzecią tabelę

create table middle_join ( 
    id integer 
, some_data varchar2(32) 
    ); 

insert into middle_join values (1, 'e'); 
insert into middle_join values (2, 'f'); 
insert into middle_join values (3, 'g'); 

wtedy, gdy w starym stylu przyłączyć Jeśli jest w środku zapytania, to nie ma żadnego błędu. Jeśli połączenie jest na "końcu" que, to ry wtedy poprawny błąd (!) zostaje podniesiony.

select * 
    from inner_join ij 
    join middle_join mj 
    on ij.id = mj.id 
    join outer_join oj 
    on ij.id = oj.id(+); 
    on ij.id = oj.id(+) 
       * 
ERROR at line 6: 
ORA-25156: old style outer join (+) cannot be used with ANSI joins 

Dlaczego tak się dzieje? Jak mogę zagwarantować, że ORA-25156 zostanie podniesiony we wszystkich przypadkach, aby uniknąć łatwych błędów i przyszłych problemów?

Przetestowałem to na 12.1.0.1, ale byłbym zaskoczony, jeśli jest to właściwe dla tej wersji ...

+0

Jeśli się nie mylę, Oracle podniosło pewne ograniczenia dotyczące starożytnej i przestarzałej składni połączenia zewnętrznego z 12c: http://docs.oracle.com/database/121/NEWFT/chapter12101.htm#FEATURENO10371 –

+0

Ostatnie dołączenie klauzula porównuje 'oj.id' ze sobą (dwukrotnie) zamiast' ij.id' lub. 'mj.id', czy możesz to poprawić i sprawdzić, czy coś się zmieniło? –

+0

Dzięki @ammoQ; nigdy nie będzie żadnych zmian, ale poprawiłem błąd. – Ben

Odpowiedz

0

Wierzę, że błąd jest podniesiona podczas próby użycia (+) w klauzuli WHERE w zapytaniu składni ANSI. Nie ma błędu, gdy próbujesz zrobić to w klauzuli ON, ponieważ w starej, nieczytelnej składni Oracle klauzula ON nie istniała.

Zgaduję, że to nieuporządkowane, że można spakować (+) do ON, ale błąd jest dla klauzuli WHERE.

+0

Pytania demonstrują błąd podniesiony w klauzuli ON. Ale to nie problem; błąd _ powinien zostać podniesiony. Problem/błąd polega na tym, że nie jest on podnoszony, jak to jest udokumentowane. – Ben