Consultas de Múltiplas Tabelas no Oracle SQL

Consultas de múltiplas tabelas permitem recuperar dados de diversas tabelas simultaneamente.

Produto Cartesiano

O produto cartesiano ocorre quando:

  1. Condições de junção são omitidas;
  2. As condições de junção são inválidas;
  3. 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

Tags: Oracle SQL Junções Multi-tabela Junção Equivalente Junção Externa

Publicado em 7-18 10:45