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 ...
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 –
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? –
Dzięki @ammoQ; nigdy nie będzie żadnych zmian, ale poprawiłem błąd. – Ben