3
SQL FUNDAMENTALS I E PROGRAM WITH
PL/SQL
1 Unidade 2 - Exibição de Dados de Várias Tabelas
1.1 Conceitos Básicos
A junção (join) é uma consulta que combina linhas de duas ou mais tabelas, views ou views
materializadas. O Oracle Database realiza uma junção sempre que múltiplas tabelas aparecem
na cláusula FROM da consulta. A lista de seleção da consulta pode selecionar todas as colunas
de qualquer uma dessas tabelas. Se duas dessas tabelas têm um nome de coluna em comum,
então o usuário deve qualificar todas as referências a essas colunas em toda a consulta com o
nome da respectiva tabela, para evitar ambiguidade.
1.2 Condições de Junção
A maioria das consultas de junção contém pelo menos uma condição de junção, quer na
cláusula FROM ou na cláusula WHERE. A condição de junção compara duas colunas, cada uma
de uma tabela diferente. Para executar a junção, o Oracle Database combina pares de linhas,
cada uma contendo uma linha de cada tabela, para o qual a condição de junção deve ser
avaliada como TRUE. As colunas que participam nas condições não precisam aparecer na lista
de seleção.
Para executar uma junção de três ou mais tabelas, o Oracle primeiramente junta duas das
tabelas com base nas condições de junção, comparando as suas colunas, e depois junta o
resultado com a outra tabela, com base nas condições de junção das colunas da outra tabela e
com as colunas do resultado. O Oracle continua este processo até que todas as tabelas
estejam associadas no resultado. O otimizador determina a ordem e junta as tabelas com base
nas condições de junção, nos índices das tabelas e em todas as estatísticas disponíveis para as
tabelas.
A cláusula WHERE, que contém as condições de junção, também pode conter outras condições
que se referem às colunas das tabelas. Essas condições podem restringir ainda mais as linhas
retornadas pela consulta de junção.
4
Quando forem necessários dados de mais de uma tabela na consulta, será usada uma condição
de junção. As linhas de uma tabela podem ser unidas às linhas de outra tabela de acordo com
os valores comuns existentes nas colunas correspondentes, ou seja, em geral, colunas de
chave primária e chave estrangeira.
Para exibir dados de duas ou mais tabelas relacionadas, o usuário deve criar uma condição de
junção na cláusula WHERE. A sintaxe da junção da Oracle é:
SELECT tabela1.coluna, tabela2.coluna FROM tabela1, tabela2 WHERE tabela1.coluna1 = tabela2.coluna2;
Na sintaxe acima:
• “tabela1.coluna” denota a tabela e a coluna a partir das quais os dados são
recuperados.
• “tabela1.coluna1 = tabela2.coluna2” é a condição que une (ou relaciona) tabelas
No exemplo abaixo:
SELECT employees.employee_id, employees.last_name, employees.department_id, departments.department_id, departments.location_id FROM employees, departments WHERE employees.department_id=
departments.department_id;
• A cláusula SELECT especifica os nomes de colunas a serem
recuperados:
o EMPLOYEE_ID, LAST_NAME, DEPARTMENT_ID, que são as
colunas contidas na tabela EMPLOYEES
5
o DEPARTMENT_ID, DEPARTMENT_NAME e LOCATION_ID, que
são as colunas contidas na tabela DEPARTMENTS
• A cláusula FROM especifica as duas tabelas que o banco de dados deve
acessar:
o tabela EMPLOYEES
o tabela DEPARTMENTS
• A cláusula WHERE especifica como as tabelas serão unidas:
employees.department_id=departments.department_id
Como a coluna DEPARTMENT_ID é comum às duas tabelas, ela deve ser precedida do nome da
tabela, a fim de evitar ambiguidade.
Qualificando Nomes de Colunas Ambíguos
O usuário precisa qualificar os nomes das colunas na cláusula WHERE com o nome da tabela, a
fim de evitar ambiguidade. Sem os prefixos de tabela, a coluna DEPARTMENT_ID pode ser
proveniente tanto da tabela DEPARTMENTS quanto da tabela EMPLOYEES. É necessário, ainda,
adicionar o prefixo de tabela para executar a consulta.
Se não houver nomes de colunas comuns às duas tabelas, não haverá necessidade de qualificar
as colunas. No entanto, o uso do prefixo de tabela melhora o desempenho, pois informa ao
Oracle Server exatamente onde localizar as colunas.
A necessidade de qualificar nomes de colunas ambíguos também se aplica às colunas que
possam ser ambíguas em outras cláusulas, como na cláusula SELECT ou na cláusula ORDER BY.
Condições de Pesquisa Adicionais
Além da junção, é possível usar critérios para a cláusula WHERE, a fim de restringir as linhas a
serem consideradas para uma ou mais tabelas da junção. Por exemplo, para exibir o número e
o nome do departamento do funcionário Matos, é necessária uma condição adicional na
cláusula WHERE.
SELECT last_name, employees.department_id, department_name
FROM employees, departments WHERE employees.department_id =
departments.department_id AND last_name = 'Matos';
6
1.3 Tipos de Junções
O banco de dados Oracle10g oferece sintaxe de junção que é compatível com SQL: 1999. Antes
da release 9i, a sintaxe de junção era diferente dos padrões ANSI ("American National
Standards Institute"). A nova sintaxe de junção compatível com SQL: 1999 não oferece
vantagens de desempenho em relação à sintaxe da junção patenteada pela Oracle existente
nas releases anteriores.
Os tipos de junções patenteados pela Oracle são:
• Equijunção;
• Não-equijunção;
• Junção externa e,
• Autojunção.
Os tipos de junções compatíveis com o padrão SQL: 1999 são:
• Junções híbridas;
• Junções naturais;
• Cláusula Using;
• Junções externas de dois lados ou completas, e
• Condições de junção arbitrárias para junções externas.
1.4 Equijunções
O relacionamento entre duas tabelas é uma equijunção – quando os valores nas colunas
utilizadas para junção são iguais. Geralmente, esse tipo de junção envolve colunas que sejam
chave primária e chave estrangeira. As equijunções também são denominadas junções simples
ou junções internas. Por exemplo:
SELECT d.department_name, e.first_name FROM departments d, employees e WHERE d.department_id = e.department_id;
7
1.5 Não-equijunções
Uma não-equijunção é uma condição de junção que não contém um operador de igualdade.
Por exemplo, o relacionamento entre a tabela EMPLOYEES e a tabela JOB_GRADES tem um
exemplo de não-equijunção. O relacionamento entre as duas tabelas baseia-se no fato de que
a coluna SALARY da tabela EMPLOYEES deve ter valores compreendidos entre os valores nas
colunas LOWEST_SALARY e HIGHEST_SALARY da tabela JOB_GRADES. Esse relacionamento é
obtido através de um operador que não seja de igualdade (=).
Exemplo de consulta com não-equijunção:
SELECT e.last_name, e.salary, j.gra FROM job_grades j, employees e WHERE e.salary BETWEEN j.lowest_sal AND j.highest_sal;
JOB_GRADES EMPLOYEES
Observa-se que todos os funcionários aparecem exatamente uma vez quando essa consulta é
executada. Nenhum funcionário é repetido na lista. Nenhuma das linhas da tabela de
classificação salarial possui classificações que se sobrepõem. Isto é, o valor do salário de um
funcionário só pode estar compreendido entre os valores de menor e maior salário de uma das
linhas da tabela de classificação salarial.
compreendidos entre os limites fornecidos pela tabela de classificação salarial.
funcionário recebe menos que o menor valor contido na coluna LOWEST_SAL nem mais que o
maior valor contido na coluna HIGHEST_SAL.
Outras condições, como <= e >=
deve se lembrar de especificar o menor valor primeiro e o maior valor depois quando estiver
usando BETWEEN.
Os apelidos de tabela foram especificados para melhorar o desempenh
possível ambiguidade.
1.6 Junções Externas
Caso uma linha não atenda a
consulta. Por exemplo:
SELECT e.last_name, e.department_id, d.department_name FROM employees e, departments d WHERE e.department_id = d.department_id;
EMPLOYEES e DEPARTMENTS,
funcionários para o departamento 190
forma, esse departamento não a
8
odos os funcionários aparecem exatamente uma vez quando essa consulta é
executada. Nenhum funcionário é repetido na lista. Nenhuma das linhas da tabela de
lassificação salarial possui classificações que se sobrepõem. Isto é, o valor do salário de um
funcionário só pode estar compreendido entre os valores de menor e maior salário de uma das
linhas da tabela de classificação salarial. Além disso, todos os salários dos funcionários estão
compreendidos entre os limites fornecidos pela tabela de classificação salarial.
funcionário recebe menos que o menor valor contido na coluna LOWEST_SAL nem mais que o
maior valor contido na coluna HIGHEST_SAL.
dições, como <= e >=, podem ser usadas, mas BETWEEN é a mais simples.
de especificar o menor valor primeiro e o maior valor depois quando estiver
Os apelidos de tabela foram especificados para melhorar o desempenho e não devido a uma
a uma condição de junção, ela não aparecerá no resultado da
SELECT e.last_name, e.department_id, d.department_name FROM employees e, departments d WHERE e.department_id = d.department_id;
EMPLOYEES e DEPARTMENTS, não há
os para o departamento 190
forma, esse departamento não aparecerá no resultado da junção.
odos os funcionários aparecem exatamente uma vez quando essa consulta é
executada. Nenhum funcionário é repetido na lista. Nenhuma das linhas da tabela de
lassificação salarial possui classificações que se sobrepõem. Isto é, o valor do salário de um
funcionário só pode estar compreendido entre os valores de menor e maior salário de uma das
rios dos funcionários estão
compreendidos entre os limites fornecidos pela tabela de classificação salarial. Nenhum
funcionário recebe menos que o menor valor contido na coluna LOWEST_SAL nem mais que o
podem ser usadas, mas BETWEEN é a mais simples. O usuário
de especificar o menor valor primeiro e o maior valor depois quando estiver
o e não devido a uma
uma condição de junção, ela não aparecerá no resultado da
SELECT e.last_name, e.department_id, d.department_name
Na
condição
de
equijunção
das tabelas
e, dessa
As linhas ausentes podem ser retornadas se um operador de junção externa for usado na
condição de junção. O operador é um sinal de mais entre parênteses (+) e é colocado ao "lado"
da junção com informações incompletas. Esse
linhas nulas, às quais podem ser unidas uma ou mais linhas da tabela completa.
Na sintaxe:
• tabela1.coluna é a condição que une (ou relaciona) as tabelas.
• tabela2.coluna(+)
em qualquer lado da condição da cláusula WHERE, mas não nos dois lados.
Deve-se colocar o símbolo de junção externa após o nome da coluna na tabela sem as linhas
correspondentes.
Por exemplo, a consulta:
SELECT e.last_name, e.departmentFROM employees e, departments d WHERE e.department_id(+) = d.department_id ;
Exibe os sobrenomes dos funcionários, os IDs e os nomes de departamento. O departamento
de contratação (Contacting) não tem funcionários
saída exibida.
9
As linhas ausentes podem ser retornadas se um operador de junção externa for usado na
condição de junção. O operador é um sinal de mais entre parênteses (+) e é colocado ao "lado"
da junção com informações incompletas. Esse operador tem a função de criar uma ou mais
linhas nulas, às quais podem ser unidas uma ou mais linhas da tabela completa.
tabela1.coluna é a condição que une (ou relaciona) as tabelas.
tabela2.coluna(+) é o símbolo de junção externa, que pode ser colocado
em qualquer lado da condição da cláusula WHERE, mas não nos dois lados.
se colocar o símbolo de junção externa após o nome da coluna na tabela sem as linhas
SELECT e.last_name, e.department_id, d.department_name FROM employees e, departments d WHERE e.department_id(+) = d.department_id ;
xibe os sobrenomes dos funcionários, os IDs e os nomes de departamento. O departamento
não tem funcionários e então o valor em branco é mostrado na
As linhas ausentes podem ser retornadas se um operador de junção externa for usado na
condição de junção. O operador é um sinal de mais entre parênteses (+) e é colocado ao "lado"
operador tem a função de criar uma ou mais
linhas nulas, às quais podem ser unidas uma ou mais linhas da tabela completa.
tabela1.coluna é a condição que une (ou relaciona) as tabelas.
pode ser colocado
em qualquer lado da condição da cláusula WHERE, mas não nos dois lados.
se colocar o símbolo de junção externa após o nome da coluna na tabela sem as linhas
_id, d.department_name
xibe os sobrenomes dos funcionários, os IDs e os nomes de departamento. O departamento
valor em branco é mostrado na
O operador de junção externa só pode aparecer em um lado da expressão, o lado com
informações incompletas. Ele retorna as linhas ausentes a partir de uma tabela que não possui
correspondências diretas na outra
externa não pode usar o operador IN nem pode estar vinculada a outra condição pelo
operador OR.
1.7 Autojunções
Autojunção permite a junção de uma
nome do gerente de cada funcionário, é necessário unir a tabela EMPLOYEES a ela mesma ou
executar uma autojunção. Por exemplo:
SELECT ger.first_name, emp.first_nameFROM employees ger, employees empWHERE ger.employee_id = emp.manager_id;
Essa consulta obtém, para cada funcionário, o nome do funcionário
manager_id de seu subordinado aponta.
número do gerente do trabalhador
gerente.
1.8 Junção com a sintaxe da SQL 1999
Ao usar a sintaxe SQL 1999, pode
anteriores com as junções patenteadas Oracle
• tabela1.coluna: denota a tabela e a coluna a partir das quais os dados são
recuperados;
10
O operador de junção externa só pode aparecer em um lado da expressão, o lado com
informações incompletas. Ele retorna as linhas ausentes a partir de uma tabela que não possui
correspondências diretas na outra tabela. Além disso, uma condição envolvendo uma junção
externa não pode usar o operador IN nem pode estar vinculada a outra condição pelo
Autojunção permite a junção de uma tabela com ela mesma. Por exemplo, para localizar o
e do gerente de cada funcionário, é necessário unir a tabela EMPLOYEES a ela mesma ou
Por exemplo:
SELECT ger.first_name, emp.first_name OM employees ger, employees emp
WHERE ger.employee_id = emp.manager_id;
obtém, para cada funcionário, o nome do funcionário-gerente cujo campo
manager_id de seu subordinado aponta. Isso faz com que o Oracle localize na mesma tabela
número do gerente do trabalhador que corresponde a um número do funcionário
nção com a sintaxe da SQL 1999
Ao usar a sintaxe SQL 1999, podem-se obter os mesmos resultados mostrados nas páginas
com as junções patenteadas Oracle. Na sintaxe:
tabela1.coluna: denota a tabela e a coluna a partir das quais os dados são
recuperados;
O operador de junção externa só pode aparecer em um lado da expressão, o lado com
informações incompletas. Ele retorna as linhas ausentes a partir de uma tabela que não possui
tabela. Além disso, uma condição envolvendo uma junção
externa não pode usar o operador IN nem pode estar vinculada a outra condição pelo
. Por exemplo, para localizar o
e do gerente de cada funcionário, é necessário unir a tabela EMPLOYEES a ela mesma ou
gerente cujo campo
faz com que o Oracle localize na mesma tabela o
número do funcionário que é
se obter os mesmos resultados mostrados nas páginas
tabela1.coluna: denota a tabela e a coluna a partir das quais os dados são
11
• CROSS JOIN: retorna um produto cartesiano das duas tabelas;
• NATURAL JOIN: une as duas tabelas com base no mesmo nome de coluna;
• JOIN tabela USING nome_coluna: executa uma equijunção com base no
nome da coluna;
• JOIN tabela ON tabela1.nome_coluna: executa uma equijunção com base na
condição da cláusula ON.
• LEFT/RIGHT/FULL OUTER: indica o tipo de junção externa
1.9 Junções Naturais
No Oracle10g, é possível deixar que a junção seja concluída automaticamente com base nas
colunas com nomes e tipos de dados correspondentes nas duas tabelas. Para isso, basta usar
as palavras-chave NATURAL JOIN. A junção só poderá ocorrer nas colunas com os mesmos
nomes e tipos de dados nas duas tabelas. Se as colunas tiverem o mesmo nome, mas tipos de
dados diferentes, a sintaxe NATURAL JOIN ocasionará um erro.
Exemplo da junção natural:
SELECT department_id, department_name, location_id, city FROM departments NATURAL JOIN locations ;
Nesse exemplo, a tabela LOCATIONS é unida à tabela DEPARTMENT por meio da coluna
LOCATION_ID, que é a única com o mesmo nome nas duas tabelas. Se outras colunas em
comum estivessem presentes, a junção teria usado todas elas.
A junção natural também pode ser expressa como uma equijunção:
SELECT department_id, department_name, departments.location_id FROM departments, locations WHERE departments.location_id = locations.location_id;
As restrições adicionais em uma junção natural são implementadas por meio de uma cláusula
WHERE. Conforme pode ser observado, a consulta restringe as linhas da saída que tem um ID
de departamento igual a 20 ou 50.
12
SELECT department_id, department_name, location_id, city FROM departments NATURAL JOIN locations WHERE department_id IN (20, 50);
1.10 Cláusula Using
As junções naturais, conforme visto anteriormente, usam todas as colunas com nomes e tipos
de dados correspondentes para unir as tabelas. A cláusula USING pode ser utilizada para
especificar apenas as colunas que devem ser usadas em uma equijunção. As colunas às quais a
cláusula USING faz referência não devem ter um qualificador (apelido ou nome de tabela) em
nenhuma parte da instrução SQL.
Por exemplo, essa instrução é válida:
SELECT l.city, d.department_name FROM locations l JOIN departments d USING (location_id) WHERE location_id = 1400;
Por outro lado, a instrução a seguir é inválida porque a coluna LOCATION_ID aparece com um
qualificador na cláusula WHERE:
SELECT l.city, d.department_name FROM locations l JOIN departments d USING (location_id) WHERE d.location_id = 1400;
O erro provocado pela instrução inválida é “ORA-25154: column part of USING clause cannot
have qualifier”.
A mesma restrição se aplica às junções do tipo NATURAL. Assim, colunas com o mesmo nome
nas duas tabelas devem ser usadas sem qualificador.
1.11 Cláusula ON
A cláusula ON deve ser utilizada para especificar uma condição de junção. Isso permite que o
usuário especifique condições de junção separadas de qualquer condição de pesquisa ou de
filtro na cláusula WHERE. Isso permite que a condição de junção seja separada de outras
condições de pesquisa. Dessa forma, pode-se dizer que a cláusula ON facilita a compreensão
do código. Por exemplo:
13
SELECT e.employee_id, e.last_name, e.department_id, d.department_id, d.location_id FROM employees e JOIN departments d ON (e.department_id = d.department_id) ;
A cláusula ON também pode ser usada para autojunção, ou seja, junção de uma tabela com ela
mesma quando as colunas possuem nomes diferentes:
SELECT e.last_name emp, m.last_name mgr FROM employees e JOIN employees m ON (e.manager_id = m.employee_id);
A cláusula ON também pode ser utilizada em uma junção tripla. Uma junção tripla consiste de
uma junção que une três tabelas. Na sintaxe compatível com SQL: 1999, as junções são
efetuadas da esquerda para a direita; sendo assim, a primeira junção a ser feita é EMPLOYEES
JOIN DEPARTMENTS.
SELECT employee_id, city, department_name FROM employees e JOIN departments d ON d.department_id = e.department_id JOIN locations l ON d.location_id = l.location_id;
14
A primeira condição de junção pode fazer referência a colunas nas tabelas EMPLOYEES e
DEPARTMENTS, mas não a colunas na tabela LOCATIONS. A segunda condição de junção pode
fazer referência a colunas de todas as três tabelas.
Esse tipo de consulta também pode ser expresso como uma equijunção tripla:
SELECT employee_id, city, department_name FROM employees, departments, locations WHERE employees.department_id =departments.department_id AND departments.location_id = locations.location_id;