Zapytanie jest poprawnym składniowo SQL, nawet jeśli table_b
nie ma name
kolumny. Powodem jest rozdzielczość zakresu.
Podczas analizy zapytania najpierw sprawdza się, czy table_b
ma name
kolumnę. Ponieważ tak nie jest, to table_a
jest sprawdzane. Zgłasza błąd tylko wtedy, gdy żadna z tabel nie ma name
kolumny.
Na koniec zapytanie jest wykonywane jako:
select a.*
from table_a a
where a.name in (select a.name
from table_b b
);
Jeśli chodzi o wyniki, zapytanie dałoby, dla każdego wiersza table_a
podzapytania (select name from table_b)
- lub (select a.name from table_b b)
- jest tabelą z pojedynczą kolumną o tej samej a.name
wartości i tyle samo wierszy co table_b
. Tak więc, jeśli table_b
ma 1 lub więcej wierszy, zapytanie działa jako:
select a.*
from table_a a
where a.name in (a.name, a.name, ..., a.name) ;
lub:
select a.*
from table_a a
where a.name = a.name ;
lub:
select a.*
from table_a a
where a.name is not null ;
Jeśli table_b
jest puste, zapytanie nie zwróci żadnych wierszy (dziękuję @ughai za wskazanie tej możliwości).
To (fakt, że nie pojawia się błąd) jest prawdopodobnie najlepszym powodem, dla którego wszystkie odwołania do kolumn powinny być poprzedzone nazwą / aliasem tabeli. Jeśli zapytanie było:
select a.* from table_a where a.name in (select b.name from table_b);
od razu dostaniesz błąd. Gdy pominięto prefiksy tabel, nie jest trudno popełnić takie błędy, szczególnie w bardziej złożonych zapytaniach, a co ważniejsze, pozostają niezauważone.
Przeczytaj także w dokumentach Oracle: Rozpoznawanie nazw w statycznych instrukcjach SQL podobny przykład B-6 w przechwytywaniu wewnętrznym i zalecenia w unikaniu wewnętrznego przechwytywania w akapitach instrukcji SELECT i DML :
Kwalifikuj każde odwołanie do kolumny w instrukcji za pomocą odpowiedniego aliasu tabeli.
Dlatego
Oznacza to, że w celu ustalenia, czy podzapytanie jest skorelowane, Oracle musi spróbować rozwiązać nazwy w podzapytaniu, w tym również w kontekście instrukcji zewnętrznych. A dla nieprefiksowanych
name
jest to jedyna możliwa rozdzielczość.źródło
Nie ma w tym
name
pola,table_b
więc Oracle bierze je ztable_a
. Próbowałem,EXPLAIN PLAN
ale dało mi to tylko to, że istniejeTABLE ACCESS
FULL
. Zakładam, że wygeneruje to pewien rodzaj produktu kartezjańskiego między dwiema tabelami, w wyniku czego lista wszystkich nazwtable_a
zostanie zwrócona przez zapytanie.źródło
from table_a where ...
. Zwróci wszystkie wiersze ztable_a
wyjątkiem tych, którename
są puste.TABLE ACCESS FULL
to tylko sposób, w jaki Oracle informuje cię, że wykonuje skanowanie sekwencyjne.