- O que é uma Inner Join?
- O que é uma junção externa?
- Executando junções externas usando o símbolo (+)
Como praticamente todos os bancos de dados relacionais, o Oracle permite a geração de consultas que combinam ou
JOIN
linhas de duas ou mais tabelas para criar o conjunto de resultados final. Embora existam vários tipos de junções que podem ser realizadas, as mais comuns são as INNER JOIN
e o OUTER JOIN
. Neste tutorial, exploraremos brevemente a diferença entre o
INNER
e OUTER JOIN
e, em seguida, examine o método abreviado que o Oracle fornece para executar OUTER JOINS
especificamente usando o +
símbolo do operador. O que é uma Inner Join?
Um
INNER JOIN
em um banco de dados relacional é simplesmente a junção de duas ou mais tabelas em que o resultado contém apenas dados que satisfaçam todas as condições de junção . Por exemplo, aqui temos uma
library
básica esquema com duas tabelas:books
e languages
. Os languages
table é apenas uma lista de nomes de idiomas possíveis e um idioma exclusivo 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
Enquanto isso, nossos
books
tabela tem um language_id
linha que para a maioria dos livros, mas não todos, simplesmente contém o language_id
associado ao idioma original publicado do livro: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
Em muitos casos, podemos desejar realizar um
INNER JOIN
dos books
e languages
tabelas, em vez de visualizar o language_id
sem sentido valor de cada livro, podemos ver o language name
em vez de. 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
O que é fundamental observar aqui é que nosso conjunto de resultados foi um pouco diferente nas duas consultas acima. No primeiro, simplesmente listamos os primeiros
10
livros, mas no INNER JOIN
query, estamos retornando apenas resultados que atendem a todas as condições de ambas as tabelas. Por esta razão, o registro de Hamlet
(que tem um language_id
valor de null
ou vazio) é ignorado e não retornado no resultado do nosso INNER JOIN
. O que é uma Outer Join?
Em vez de retornar exclusivamente resultados que satisfaçam todas as condições de junção de um
INNER JOIN
, um OUTER JOIN
retorna não apenas resultados que satisfazem todas as condições, mas também retorna linhas de uma tabela que não satisfez a condição. A tabela que é escolhida para este “bypass” de requisitos condicionais é determinada pela direcionalidade ou “lado” da junção, normalmente chamada de LEFT
ou RIGHT
juntas externas. Ao definir um lado para seu
OUTER JOIN
, você está especificando qual tabela sempre retornará sua linha mesmo que a oposta a tabela do outro lado da junção está ausente ou null
valores como parte da condição de junção. Portanto, se executarmos o mesmo
JOIN
básico como acima para recuperar books
e language names
, sabemos que nossos books
tabela deve sempre retornar dados, então nosso JOIN
lado deve "apontar para" nossos books
tabela, tornando assim os languages
tabela o OUTER
tabela que estamos anexando a ela. Para isso, basta alterar:
books b INNER JOIN library.languages l
…para isso:
books b LEFT OUTER JOIN library.languages l
Assim, toda a consulta e o conjunto de resultados parecem quase idênticos ao
INNER JOIN
exceto essa pequena alteração: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
Como esperado, usando um
LEFT OUTER JOIN
em vez do anterior INNER JOIN
, estamos obtendo o melhor dos dois mundos:não vamos pular nenhum books
registros (como Hamlet
) simplesmente porque o language_id
valor é null
para esse registro, mas para todos os registros em que language_id
existe, obtemos o language name
bem formatado obtido de nossos languages
tabela. Executando junções externas usando o símbolo (+)
Conforme indicado na documentação oficial, a Oracle fornece um
outer join operator
especial (o +
símbolo) que é uma abreviação para executar OUTER JOINS
. Na prática, o
+
símbolo é colocado diretamente na condicional e no lado da tabela opcional (aquela que pode conter valores vazios ou null
valores dentro da condicional). Portanto, podemos mais uma vez reescrever nosso
LEFT OUTER JOIN
acima declaração usando o +
operador assim: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;
Os resultados são os mesmos que o padrão
LEFT OUTER JOIN
exemplo acima, então não vamos incluí-los aqui. No entanto, há um aspecto crítico a ser observado sobre a sintaxe usando o +
operador para OUTER JOINS
. O
+
operador deve estar no lado esquerdo da condicional (à esquerda do igual a =
sinal). Portanto, neste caso, porque queremos garantir que nossos languages
table é a tabela opcional que pode retornar null
valores durante esta comparação, trocamos a ordem das tabelas nesta condicional, então languages
está à esquerda (e é opcional) enquanto books
está à direita. Por fim, devido a essa reordenação dos lados da tabela na condicional ao usar o
+
operador, é importante perceber que o acima é simplesmente um atalho para um RIGHT OUTER JOIN
. Isso significa que este snippet da consulta:FROM
books b,
library.languages l
WHERE
l.id (+)= b.language_id
…é efetivamente idêntico a isso:
FROM
library.languages l
RIGHT OUTER JOIN
books b
ON
b.language_id = l.id