- Co to jest połączenie wewnętrzne?
- Co to jest złącze zewnętrzne?
- Wykonywanie połączeń zewnętrznych za pomocą symbolu (+)
Podobnie jak praktycznie wszystkie relacyjne bazy danych, Oracle umożliwia generowanie zapytań, które łączą lub JOIN
wiersze z dwóch lub więcej tabel, aby utworzyć ostateczny zestaw wyników. Chociaż istnieje wiele rodzajów złączeń, które można wykonać, najczęstsze to INNER JOIN
i OUTER JOIN
.
W tym samouczku krótko omówimy różnicę między INNER
i OUTER JOIN
a następnie przyjrzyj się skróconej metodzie Oracle do wykonywania OUTER JOINS
konkretnie za pomocą +
symbol operatora.
Co to jest połączenie wewnętrzne?
INNER JOIN
w relacyjnej bazie danych to po prostu połączenie dwóch lub więcej tabel, w których wynik będzie zawierał tylko te dane, które spełniają wszystkie warunki połączenia .
Na przykład tutaj mamy podstawową library
schemat z dwiema tabelami:books
i languages
. languages
tabela to tylko lista możliwych nazw języków i unikalny język id
:
SELECT * FROM library.languages;
id name
1 English
2 French
3 German
4 Mandarin
5 Spanish
6 Arabic
7 Japanese
8 Russian
9 Greek
10 Italian
Tymczasem nasze books
tabela ma language_id
wiersz, który w większości książek, ale nie we wszystkich, zawiera po prostu language_id
powiązany z oryginalnym językiem publikacji książki:
SELECT * FROM
books
ORDER BY
id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language_id
1 In Search of Lost Time Marcel Proust 1913 2
2 Ulysses James Joyce 1922 1
3 Don Quixote Miguel de Cervantes 1605 5
4 Moby Dick Herman Melville 1851 1
5 Hamlet William Shakespeare 1601 (null)
6 War and Peace Leo Tolstoy 1869 8
7 The Odyssey Homer -700 9
8 The Great Gatsby F. Scott Fitzgerald 1925 1
9 The Divine Comedy Dante Alighieri 1472 10
10 Madame Bovary Gustave Flaubert 1857 2
W wielu przypadkach możemy chcieć wykonać INNER JOIN
z books
i languages
tabele więc zamiast przeglądać bezsensowny language_id
wartości każdej książki, faktycznie możemy zobaczyć language name
zamiast tego.
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b
INNER JOIN
library.languages l
ON
b.language_id = l.id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language
1 In Search of Lost Time Marcel Proust 1913 French
2 Ulysses James Joyce 1922 English
3 Don Quixote Miguel de Cervantes 1605 Spanish
4 Moby Dick Herman Melville 1851 English
6 War and Peace Leo Tolstoy 1869 Russian
7 The Odyssey Homer -700 Greek
8 The Great Gatsby F. Scott Fitzgerald 1925 English
9 The Divine Comedy Dante Alighieri 1472 Italian
10 Madame Bovary Gustave Flaubert 1857 French
11 The Brothers Karamazov Fyodor Dostoyevsky 1880 Russian
Należy tutaj zauważyć, że nasz zestaw wyników był nieco inny w dwóch powyższych zapytaniach. W pierwszym po prostu wymieniliśmy pierwsze 10
książki, ale w INNER JOIN
zapytanie zwracamy tylko wyniki spełniające wszystkie warunki z obu tabel. Z tego powodu zapis Hamlet
(który ma language_id
wartość null
lub puste) jest ignorowane i nie jest zwracane w wyniku naszego INNER JOIN
.
Co to jest złącze zewnętrzne?
Zamiast zwracać wyłącznie wyniki, które spełniają wszystkie warunki złączenia INNER JOIN
, OUTER JOIN
zwraca nie tylko wyniki, które spełniają wszystkie warunki, ale również zwraca wiersze z jednej tabeli, które nie spełniły warunku. Tabela wybrana do tego „pominięcia” wymagań warunkowych jest określona przez kierunek lub „stronę” złączenia, zwykle określaną jako LEFT
lub RIGHT
połączenia zewnętrzne.
Podczas definiowania strony do OUTER JOIN
, określasz, która tabela zawsze zwróci swój wiersz, nawet jeśli przeciwny w tabeli po drugiej stronie złączenia brakuje lub null
wartości jako część warunku połączenia.
Dlatego jeśli wykonamy to samo podstawowe JOIN
jak powyżej, aby pobrać books
i language names
, wiemy, że nasze books
tabela powinna zawsze zwracać dane, więc nasze JOIN
strona powinna „wskazywać” nasze books
tabeli, tworząc w ten sposób languages
tabela OUTER
tabeli, którą do niej dołączamy.
Aby to osiągnąć, po prostu zmieniamy:
books b INNER JOIN library.languages l
…do tego:
books b LEFT OUTER JOIN library.languages l
W ten sposób całe zapytanie i zestaw wyników wygląda prawie identycznie jak INNER JOIN
poza tą drobną zmianą:
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b
LEFT OUTER JOIN
library.languages l
ON
b.language_id = l.id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
id title author year_published language
1 In Search of Lost Time Marcel Proust 1913 French
2 Ulysses James Joyce 1922 English
3 Don Quixote Miguel de Cervantes 1605 Spanish
4 Moby Dick Herman Melville 1851 English
5 Hamlet William Shakespeare 1601 (null)
6 War and Peace Leo Tolstoy 1869 Russian
7 The Odyssey Homer -700 Greek
8 The Great Gatsby F. Scott Fitzgerald 1925 English
9 The Divine Comedy Dante Alighieri 1472 Italian
10 Madame Bovary Gustave Flaubert 1857 French
Zgodnie z oczekiwaniami, używając LEFT OUTER JOIN
zamiast poprzedniego INNER JOIN
, czerpiemy to, co najlepsze z obu światów:nie pomijamy żadnych books
rekordy (takie jak Hamlet
) po prostu dlatego, że language_id
wartość to null
dla tego rekordu, ale dla wszystkich rekordów, w których language_id
istnieje, otrzymujemy ładnie sformatowaną language name
uzyskane z naszych languages
tabela.
Wykonywanie połączeń zewnętrznych przy użyciu symbolu (+)
Jak wskazano w oficjalnej dokumentacji, Oracle zapewnia specjalny outer join operator
(+
symbol), który jest skrótem do wykonywania OUTER JOINS
.
W praktyce +
symbol jest umieszczony bezpośrednio w warunku oświadczenie i po stronie opcjonalnej tabeli (tej, która może zawierać pustą lub null
wartości w ramach warunkowego).
Dlatego możemy ponownie przepisać powyższe LEFT OUTER JOIN
oświadczenie za pomocą +
taki operator:
SELECT
b.id,
b.title,
b.author,
b.year_published,
l.name language
FROM
books b,
library.languages l
WHERE
l.id (+)= b.language_id
ORDER BY
b.id
FETCH FIRST 10 ROWS ONLY;
Wyniki są takie same jak w przypadku standardowego LEFT OUTER JOIN
przykład powyżej, więc nie będziemy ich tutaj uwzględniać. Jest jednak jeden krytyczny aspekt, który należy zwrócić uwagę na składnię przy użyciu +
operator dla OUTER JOINS
.
+
operator musi być po lewej stronie warunku (po lewej stronie równa się =
znak). Dlatego w tym przypadku, ponieważ chcemy mieć pewność, że nasze languages
table to opcjonalna tabela, która może zwrócić null
wartości podczas tego porównania zamieniliśmy kolejność tabel w tym warunku, więc languages
znajduje się po lewej stronie (i jest opcjonalne), podczas gdy books
jest po prawej stronie.
Wreszcie, z powodu tej zmiany kolejności boków tabeli w trybie warunkowym przy użyciu +
operatora, ważne jest, aby zdać sobie sprawę, że powyższe jest po prostu skrótem dla RIGHT OUTER JOIN
. Oznacza to, że ten fragment zapytania:
FROM
books b,
library.languages l
WHERE
l.id (+)= b.language_id
…jest w rzeczywistości identyczny z tym:
FROM
library.languages l
RIGHT OUTER JOIN
books b
ON
b.language_id = l.id