Consultas de múltiplas tabelas permitem recuperar dados de diversas tabelas simultaneamente.
Produto Cartesiano
O produto cartesiano ocorre quando:
- Condições de junção são omitidas;
- As condições de junção são inválidas;
- Todas as linhas de todas as tabelas são combinadas entre si.
SELECT *
FROM funcionarios;
| FUNC_ID |
NOME_FUNC |
DEPT_ID |
CARGO_ID |
SALARIO |
COMISSAO |
DATA_CONTRATACAO |
| 1 |
Ana |
1 |
PM |
12000 |
(nulo) |
2008-10-20T00:00:00Z |
| 2 |
Bruno |
1 |
DEV |
6000 |
0.15 |
2018-05-12T00:00:00Z |
| 3 |
Carla |
2 |
QA |
7000 |
0.08 |
2011-07-22T00:00:00Z |
| 4 |
Daniel |
2 |
AM |
4500 |
0.25 |
2020-02-15T00:00:00Z |
| 5 |
Elena |
2 |
DEV |
9000 |
0.10 |
2009-03-05T00:00:00Z |
SELECT *
FROM departamentos;
| DEPT_ID |
NOME_DEPT |
LOCAL_ID |
| 1 |
Desenvolvimento |
1 |
| 2 |
Comercial |
2 |
SELECT f.nome_func, d.dept_id
FROM funcionarios f, departamentos d;
| NOME_FUNC |
DEPT_ID |
| Ana |
1 |
| Bruno |
1 |
| Carla |
1 |
| Daniel |
1 |
| Elena |
1 |
| Ana |
2 |
| Bruno |
2 |
| Carla |
2 |
| Daniel |
2 |
| Elena |
2 |
Para evitar o produto cartesiano, inclua condições de junção válidas na cláusula WHERE.
Tipos de Junções
No SQL:1999, existem junções como:
- Junção Cruzada (Cross joins)
- Junção Natural (Natural joins)
- Junção com USING (Using clause)
- Junção Externa Completa (Full outer joins)
- Junção Externa com Condições Arbitrárias
Para versões mais antigas do Oracle (como 8i), utiliza-se:
- Junção Equivalente (Equijoin)
- Junção Não Equivalente (Non-equijoin)
- Junção Externa (Outer join)
- Junção Própria (Self join)
A junção interna retorna apenas linhas com correspondência. A junção esquerda usa a tabela da esquerda como base, preenchendo com nulos onde não há correspondência à direita. A junção direita faz o oposto. A junção completa retorna todas as linhas de ambas as tabelas, com nulos quando não há correspondência. A junção cruzada combina cada linha da tabela esquerda com todas da direita, equivalendo ao produto cartesieno.
Junções no Oracle
Para consultar dados de múltiplas tabelas, utilize condições de junção na cláusula WHERE. Se houver colunas com o mesmo nome, qualifique com o nome da tabela.
Junção Equivalente
SELECT tabela1.coluna, tabela2.coluna
FROM tabela1, tabela2
WHERE tabela1.coluna1 = tabela2.coluna2;
SELECT f.nome_func, f.dept_id, d.dept_id, d.local_id
FROM funcionarios f, departamentos d
WHERE f.dept_id = d.dept_id;
| NOME_FUNC |
DEPT_ID |
DEPT_ID |
LOCAL_ID |
| Bruno |
1 |
1 |
1 |
| Ana |
1 |
1 |
1 |
| Elena |
2 |
2 |
2 |
| Daniel |
2 |
2 |
2 |
| Carla |
2 |
2 |
2 |
Apelidos de Tabela
Utilize apelidos para simplificar consultas.
SELECT f.nome_func, f.dept_id, d.dept_id, d.local_id
FROM funcionarios f, departamentos d
WHERE f.dept_id = d.dept_id;
Junção de Múltiplas Tabelas
Para conectar n tabelas, são necessárias pelo menos n-1 condições de junção.
SELECT f.nome_func, d.nome_dept, l.cidade_local
FROM funcionarios f, departamentos d, localizacoes l
WHERE f.dept_id = d.dept_id
AND d.local_id = l.local_id;
| NOME_FUNC |
NOME_DEPT |
CIDADE_LOCAL |
| Ana |
Desenvolvimento |
São Paulo |
| Bruno |
Desenvolvimento |
São Paulo |
| Carla |
Comercial |
Rio de Janeiro |
| Daniel |
Comercial |
Rio de Janeiro |
| Elena |
Comercial |
Rio de Janeiro |
Junção Não Equivalente
SELECT *
FROM faixas_salariais;
| FAIXA |
SALARIO_MIN |
SALARIO_MAX |
| A |
25000 |
35000 |
| B |
12000 |
24999 |
| C |
6000 |
11999 |
| D |
0 |
5999 |
SELECT f.nome_func, f.salario, fs.faixa
FROM funcionarios f, faixas_salariais fs
WHERE f.salario BETWEEN fs.salario_min AND fs.salario_max;
| NOME_FUNC |
SALARIO |
FAIXA |
| Daniel |
4500 |
D |
| Bruno |
6000 |
C |
| Carla |
7000 |
C |
| Elena |
9000 |
C |
| Ana |
12000 |
B |
Junção Externa
Utilize o símbolo (+) para incluir dados que não satisfazem as condições de junção.
SELECT *
FROM departamentos;
| DEPT_ID |
NOME_DEPT |
LOCAL_ID |
| 1 |
Desenvolvimento |
1 |
| 2 |
Comercial |
2 |
| 3 |
Qualidade |
4 |
SELECT *
FROM localizacoes;
| LOCAL_ID |
CIDADE_LOCAL |
| 1 |
São Paulo |
| 2 |
Rio de Janeiro |
| 3 |
Belo Horizonte |
Observe que QUALIDADE tem LOCAL_ID=4 sem correspondência em localizacoes, e BELO HORIZONTE tem LOCAL_ID=3 sem correspondência em departamentos.
Junção Externa Esquerda (Oracle)
SELECT l.local_id, l.cidade_local, d.dept_id
FROM localizacoes l, departamentos d
WHERE l.local_id(+) = d.local_id;
| LOCAL_ID |
CIDADE_LOCAL |
DEPT_ID |
| 1 |
São Paulo |
1 |
| 2 |
Rio de Janeeiro |
2 |
| (nulo) |
(nulo) |
3 |
Junção Externa Direita (Oracle)
SELECT l.local_id, l.cidade_local, d.dept_id
FROM localizacoes l, departamentos d
WHERE l.local_id = d.local_id(+);
| LOCAL_ID |
CIDADE_LOCAL |
DEPT_ID |
| 1 |
São Paulo |
1 |
| 2 |
Rio de Janeiro |
2 |
| 3 |
Belo Horizonte |
(nulo) |
Junção Própria
SELECT trab.nome_func, trab.gerente_id, gerente.func_id, gerente.nome_func
FROM funcionarios trab, funcionarios gerente
WHERE trab.gerente_id = gerente.func_id;
| NOME_FUNC |
GERENTE_ID |
FUNC_ID |
NOME_FUNC |
| Elena |
1 |
1 |
Ana |
| Bruno |
1 |
1 |
Ana |
| Carla |
2 |
2 |
Bruno |
Junções com Sintaxe SQL:1999
SELECT tabela1.coluna, tabela2.coluna
FROM tabela1
[CROSS JOIN tabela2] |
[NATURAL JOIN tabela2] |
[JOIN tabela2 USING (nome_coluna)] |
[JOIN tabela2 ON (tabela1.coluna = tabela2.coluna)] |
[LEFT|RIGHT|FULL OUTER JOIN tabela2 ON (tabela1.coluna = tabela2.coluna)];
Junção Cruzada
Equivalente ao produto cartesiano, utiliza CROSS JOIN.
SELECT d.local_id, l.local_id
FROM departamentos d CROSS JOIN localizacoes l;
| LOCAL_ID |
LOCAL_ID |
| 1 |
1 |
| 1 |
2 |
| 1 |
3 |
| 2 |
1 |
| 2 |
2 |
| 2 |
3 |
| 4 |
1 |
| 4 |
2 |
| 4 |
3 |
Junção Natural
Utiliza NATURAL JOIN para conectar tabelas por colunas com o mesmo nome e tipo.
SELECT nome_dept, local_id, cidade_local
FROM departamentos NATURAL JOIN localizacoes;
| NOME_DEPT |
LOCAL_ID |
CIDADE_LOCAL |
| Desenvolvimento |
1 |
São Paulo |
| Comercial |
2 |
Rio de Janeiro |
Não é possível qualificar colunas com nome da tabela em junções naturais.
Junção com USING
Use USING para especificar colunas de junção quando há múltiplas colunas com o mesmo nome.
SELECT f.nome_func, d.local_id
FROM funcionarios f JOIN departamentos d
USING (dept_id);
| NOME_FUNC |
LOCAL_ID |
| Ana |
1 |
| Bruno |
1 |
| Carla |
2 |
| Daniel |
2 |
| Elena |
2 |
Junção com ON
Utilize ON para condições de junção explícitas e mais legíveis.
SELECT f.nome_func, d.local_id
FROM funcionarios f JOIN departamentos d
ON f.dept_id = d.dept_id;
Junção de Múltiplas Tabelas com ON
SELECT f.nome_func, d.nome_dept, l.cidade_local
FROM funcionarios f
JOIN departamentos d
ON f.dept_id = d.dept_id
JOIN localizacoes l
ON d.local_id = l.local_id;
Junções Externas com SQL:1999
Junção Externa Esquerda
SELECT l.local_id, l.cidade_local, d.dept_id
FROM localizacoes l
LEFT OUTER JOIN departamentos d
ON l.local_id = d.local_id;
| LOCAL_ID |
CIDADE_LOCAL |
DEPT_ID |
| 1 |
São Paulo |
1 |
| 2 |
Rio de Janeiro |
2 |
| 3 |
Belo Horizonte |
(nulo) |
Junção Externa Direita
SELECT l.local_id, l.cidade_local, d.dept_id
FROM localizacoes l
RIGHT OUTER JOIN departamentos d
ON l.local_id = d.local_id;
| LOCAL_ID |
CIDADE_LOCAL |
DEPT_ID |
| 1 |
São Paulo |
1 |
| 2 |
Rio de Janeiro |
2 |
| (nulo) |
(nulo) |
3 |
Junção Externa Completa
SELECT l.local_id, l.cidade_local, d.dept_id
FROM localizacoes l
FULL OUTER JOIN departamentos d
ON l.local_id = d.local_id;
| LOCAL_ID |
CIDADE_LOCAL |
DEPT_ID |
| 1 |
São Paulo |
1 |
| 2 |
Rio de Jeneiro |
2 |
| (nulo) |
(nulo) |
3 |
| 3 |
Belo Horizonte |
(nulo) |
Adicionando Condições de Junção
SELECT f.nome_func, d.local_id
FROM funcionarios f JOIN departamentos d
ON f.dept_id = d.dept_id
AND f.gerente_id = 1;
| NOME_FUNC |
LOCAL_ID |
| Bruno |
1 |
| Elena |
2 |