Sei sulla pagina 1di 56

Junção de Tabelas

Junção de Tabelas A figura abaixo resume as operações de junção: As operações de junção dividem-se

A figura abaixo resume as operações de junção:

Tabelas A figura abaixo resume as operações de junção: As operações de junção dividem-se em dois

As operações de junção dividem-se em dois grupos: horizontais e verticais. As horizontais actuam sobre linhas enquanto as verticais actuam sobre colunas.

Junção horizontal

Utiliza-se uma junção horizontal quando a consulta SQL requer dados de duas ou mais tabelas. Esta é a operação que na prática tira partido do conceito "base de dados relacional" pois permite mostrar os dados que estão armazenados em diferentes tabelas como se estivessem armazenados numa única, desde que essas tabelas possuam um relacionamento entre si. A tabela resultado é construída a partir de uma das tabelas originais, acrescentando colunas da segunda tabela, o que corresponde a um crescimento horizontal.

A norma SQL99 define a sintaxe usada pelas cláusulas do comando SELECT

para fazer os diferentes tipos de junção. A base de dados Oracle suporta esta sintaxe desde a versão 9.0. Nas versões anteriores à 9.0 era usada uma sintaxe

antiga, que no caso da junção externa possuia uma notação proprietária. Por razões de compatibilidade com o passado a sintaxe antiga com as extensões

proprietárias contínua disponível. Neste manual os comandos serão dados seguindo as duas abordagens: sintaxe antiga e SQL99.

Produto cartesiano

duas abordagens: sintaxe antiga e SQL99. Produto cartesiano O produto cartesiano entre dois conjuntos é um

O produto cartesiano entre dois conjuntos é um terceiro conjunto constituído por todos os elementos do primeiro combinados com todos os elementos do segundo.

Os comandos abaixo geram o produto cartesiado entre as tabelas EMP e DEP:

 

Sintaxe antiga

SQL99

SELECT emp.empno, emp.ename, emp.deptno, dept.deptno, dept.dname FROM emp, dept;

 

SELECT emp.empno, emp.ename, emp.deptno, dept.deptno, dept.dname FROM emp CROSS JOIN dept;

EMPNO

ENAME

DEPTNO

DEPTNO

DNAME

---------------------- ---------- ---------------------- ------------- --------- --------------

7369

SMITH

20

10

ACCOUNTING

7499

ALLEN

30

10

ACCOUNTING

7521

WARD

30

10

ACCOUNTING

7566

JONES

20

10

ACCOUNTING

7654

MARTIN

30

10

ACCOUNTING

7698

BLAKE

30

10

ACCOUNTING

7782

CLARK

10

10

ACCOUNTING

7788

SCOTT

20

10

ACCOUNTING

7839

KING

10

10

ACCOUNTING

7844

TURNER

30

10

ACCOUNTING

7876

ADAMS

20

10

ACCOUNTING

7900

JAMES

30

10

ACCOUNTING

7902

FORD

20

10

ACCOUNTING

7934

MILLER

10

10

ACCOUNTING

7369

SMITH

20

20

RESEARCH

7499

ALLEN

30

20

RESEARCH

7521

WARD

30

20

RESEARCH

7566

JONES

20

20

RESEARCH

7654

MARTIN

30

20

RESEARCH

7698

BLAKE

30

20

RESEARCH

7782

CLARK

10

20

RESEARCH

7788

SCOTT

20

20

RESEARCH

7839

KING

10

20

RESEARCH

7844

TURNER

30

20

RESEARCH

7876

ADAMS

20

20

RESEARCH

7900

JAMES

30

20

RESEARCH

7902

FORD

20

20

RESEARCH

7934

MILLER

10

20

RESEARCH

7369

SMITH

20

30

SALES

7499

ALLEN

30

30

SALES

7521

WARD

30

30

SALES

7566

JONES

20

30

SALES

7654

MARTIN

30

30

SALES

7698

BLAKE

30

30

SALES

7782

CLARK

10

30

SALES

7788

SCOTT

20

30

SALES

7839

KING

10

30

SALES

7844

TURNER

30

30

SALES

7876

ADAMS

20

30

SALES

7900

JAMES

30

30

SALES

7902

FORD

20

30

SALES

7934

MILLER

10

30

SALES

7369

SMITH

20

40

OPERATIONS

7499

ALLEN

30

40

OPERATIONS

7521

WARD

30

40

OPERATIONS

7566

JONES

20

40

OPERATIONS

7654

MARTIN

30

40

OPERATIONS

7698

BLAKE

30

40

OPERATIONS

7782

CLARK

10

40

OPERATIONS

7788

SCOTT

20

40

OPERATIONS

7839

KING

10

40

OPERATIONS

7844

TURNER

30

40

OPERATIONS

7876

ADAMS

20

40

OPERATIONS

7900

JAMES

30

40

OPERATIONS

7902

FORD

20

40

OPERATIONS

7934

MILLER

10

40

OPERATIONS

56 rows selected

MILLER 10 40 OPERATIONS 56 rows selected  Na sintaxe proprietária o produto cartesiano é obtido

Na sintaxe proprietária o produto cartesiano é obtido quando se faz referencia a mais que duas tabelas e não se coloca uma condição de JOIN na cláusula WHERE;

Na sintaxe SQL99 o produto cartesiano é obtido usando a cláusula CROSS JOIN;

A sintaxe SQL99 é menos susceptível a erros, pois é preciso usar explicitamente a cláusula CROSS JOIN, enquanto que na sintaxe proprietária, se houver esquecimento da cláusula de JOIN ou erro na sua construção, sai um produto cartesiano;

O resultado do produto cartesiano raramente é útil, pois mostra combinações de linhas que não têm relação entre si e por isso não são úteis para o utilizador. A sua execução causa muito I/O na base de dados;

Junção Interna

Sumário

por isso não são úteis para o utilizador. A sua execução causa muito I/O na base

A junção interna é uma operação de junção horizontal entre duas tabelas, que

usa uma comparação por igualdade entre a(s) coluna(s) comum(ns). Normalmente a(s) coluna(s) comum(ns) é(são) Foreign Key numa tabela e Primary Key ou Unique Key na outra. A junção interna pode ser vista como um produto cartesiano filtrado, pois exige que as linhas da tabela da esquerda tenham correspondente na tabela da direita, sendo o valor da coluna comum igual. O diagrama apresentado a seguir mostra como funciona a junção interna entre duas tabelas:

mostra como funciona a junção interna entre duas tabelas: A junção interna é a operação mais

A junção interna é a operação mais importante nas bases de dados relacionais,

pelo que é suportada desde sempre. A norma SQL99 propos uma nova sintaxe para esta operação, tendo disponibilizado várias cláusulas que serão analisadas nos exemplos abaixo, onde também faremos a comparação com a sintaxe

antiga. Os temas abordados serão:

Cláusula ON

As tabelas EMP e DEPT possuem uma relação entre si, implementada através da coluna comum DEPTNO. Na tabela EMP sabemos qual o número do departamento em que o empregado trabalha. Na tabela DEPT sabemos o número, nome e localização desse departamento. Para juntar os dois conjuntos efectuamos uma JUNÇÃO horizontaldas duas tabelas, usando uma igualdade de valores na coluna comum, como ilustrado nos exemplos abaixo:

Sintaxe antiga

SQL99

SELECT emp.empno,

SELECT emp.empno,

emp.ename, emp.deptno, dept.deptno, dept.dname, dept.loc FROM emp, dept WHERE emp.deptno=dept.deptno;

 

emp.ename, emp.deptno, dept.deptno, dept.dname, dept.loc FROM emp INNER JOIN dept ON (emp.deptno=dept.deptno);

EMPNO

ENAME

DEPTNO

DEPTNO

DNAME

LOC

---------------------- ---------- ---------------------- -------------

--------- -------------- -------------

 

7369

SMITH

20

20

RESEARCH

DALLAS

7499

ALLEN

30

30

SALES

CHICAGO

7521

WARD

30

30

SALES

CHICAGO

7566

JONES

20

20

RESEARCH

DALLAS

7654

MARTIN

30

30

SALES

CHICAGO

7698

BLAKE

30

30

SALES

CHICAGO

7782

CLARK

10

10

ACCOUNTING

NEW YORK

7788

SCOTT

20

20

RESEARCH

DALLAS

7839

KING

10

10

ACCOUNTING

NEW YORK

7844

TURNER

30

30

SALES

CHICAGO

7876

ADAMS

20

20

RESEARCH

DALLAS

7900

JAMES

30

30

SALES

CHICAGO

7902

FORD

20

20

RESEARCH

DALLAS

7934

MILLER

10

10

ACCOUNTING

NEW YORK

14 rows selected

 
10 ACCOUNTING NEW YORK 14 rows selected    Com esta operação o utilizador consegue visualizar

Com esta operação o utilizador consegue visualizar o nome do empregado, o nome do departamento em que trabalha e a sua localização, ou seja, vê os dados de duas tabelas relacionadas como se fossem uma única;

Esta junção pode ser interpretada como um produto cartesiano ao qual foram eliminadas as linhas que não satisfazem a condição de junção;

O comentário anterior mostra como interpretar a junção em comparação com o produto cartesiano, mas não revela a forma como o

motor da base de dados efectivamente resolve a operação. Esta operação é tão importante que os construtores de motores relacionais investem muitos recursos para optimizar o desempenho, o que resulta na existência de vários meios para executar a junção, que dependem da dimensão das tabelas envolvidas, da existência de índices e da selectividade das colunas comuns. Produzir um produto cartesiano e depois filtrar linhas é um meio muito dispendioso em termos de I/O e processamento, pelo que os motores recorrem a outros caminhos, cuja explicação mais detalhada está fora do âmbito deste curso;

As tabelas DEPT e EMP têm em comum a coluna DEPTNO pelo que nos comandos houve necessidade de distinguir de qual das tabelas queremos obter a coluna. Sempre que há ambiguidade nos nomes das colunas o utilizador é obrigado a indicar o nome da tabela a que pertence a coluna pretendida. Por exemploEMP.DEPTNO e DEPT.DEPTNO;

A maioria das operações de junção são internas (INNER) pelo que a palavra reservada INNER é facultativa;

Cláusula USING

A cláusula USING está disponível na sintaxe SQL99 e pode ser usada em vez da cláusula ON sempre que a(s) coluna(s) usada(s) na junção tenha(m) o mesmo nome em ambas as tabelas. Esta cláusula pode ser usada mesmo que existam outras colunas com o mesmo nome em ambas as tabelas.

No caso das tabelas EMP e DEPT a junção pode ser feita com USING:

Sintaxe antiga

SQL99

SELECT emp.empno, emp.ename, emp.deptno, dept.deptno, dept.dname, dept.loc FROM emp, dept WHERE emp.deptno=dept.deptno;

SELECT emp.empno, emp.ename, deptno, dept.dname, dept.loc FROM emp INNER JOIN dept USING (deptno);

; SELECT emp.empno, emp.ename, deptno , dept.dname, dept.loc FROM emp INNER JOIN dept USING (deptno) ;

Esta cláusula facilita a escrita do query, mas requer a validação prévia de que a(s) coluna(s) usada(s) na junção tem(êm) o mesmo nome em ambas as tabelas;

A cláusula USING obriga a que a(s) coluna(s) usada(s) na junção seja(m) referenciada(s) sem o nome da tabela a que pertence(m);

referenciada(s) sem o nome da tabela a que pertence(m); T opo Cláusula NATURAL JOIN A cláusula

Cláusula NATURAL JOIN

A cláusula NATURAL JOIN está disponível na sintaxe SQL99 e pode ser usada em vez da cláusula ON ou em vez da cláusula USING sempre que:

A(s) coluna(s) usada(s) na junção tenha(m) o mesmo nome em ambas as tabelas;

A(s) coluna(s) usada(s) na junção é(são) a(s) única(s) com o mesmo nome em ambas as tabelas;

No caso das tabelas EMP e DEPT a junção pode ser feita com NATURAL JOIN:

Sintaxe antiga

SQL99

SELECT emp.empno, emp.ename, emp.deptno, dept.deptno, dept.dname, dept.loc FROM emp, dept WHERE emp.deptno=dept.deptno;

SELECT emp.empno, emp.ename, deptno, dept.dname, dept.loc FROM emp NATURAL JOIN dept;

deptno , dept.dname, dept.loc FROM emp NATURAL JOIN dept ;  Esta cláusula facilita a escrita

Esta cláusula facilita a escrita do query pois o utilizador não tem que referir qual(ais) a(s) coluna(s) que vai usar na junção;

Esta cláusula requer a validação prévia não só de que a(s) coluna(s) usada(s) na junção tem(êm) o mesmo nome em ambas as tabelas mas também que é(são) a(s) única(s) coluna(s) comum(ns);

A cláusula NATURAL JOIN obriga a que a(s) coluna(s) usada(s) na junção seja(m) referenciada(s) sem o nome da tabela a que pertence(m);

obriga a que a(s) coluna(s) usada(s) na junção seja(m) referenciada(s) sem o nome da tabela a

Comparação entre ON, USING e NATURAL JOIN

Consideremos as seguintes situações:

 

NAT

Sit

       

URA

uaç

Modelo entidade relacionamento

Sintaxe

antiga

ON

USIN

G

L

ão

JOI

 

N

 
      SELECT  
   

SELECT

 

1

SELECT *

FROM t1,

t2

WHERE

t1.t1_c1

=t2.t1_c

1;

SELECT *

FROM t1

INNER

JOIN t2

ON

(t1.t1_c

1=t2.t1_

*

FROM

t1

INNER

JOIN

t2

USING

SELE

CT *

FROM

t1

NATU

RAL

JOIN

c1);

(t1_c1

t2;

);

     

SELECT *

   
SELECT * FROM t3 SELECT

SELECT *

FROM t3

SELECT

FROM t3,

INNER

*

2

t4

WHERE

t3.t3_c1

=t4.t3_c

1

AND

t3.t3_c2

JOIN t4

ON

(t3.t3_c

1=t4.t3_

c1

AND

FROM

t3

INNER

JOIN

t4

USING

(t3_c1

SELE

CT *

FROM

t3

NATU

RAL

JOIN

t4;

=t4.t3_c

t3.t3_c2

,t3_c2

2;

=t4.t3_c

);

 

2);

 
    SELECT *    
 

SELECT *

   

3

SELECT *

FROM t5,

t6

WHERE

t5.t5_c1

=t6.t6_c

2;

FROM t5

INNER

JOIN t6

ON

(t5.t5_c

1=t6.t6_

c2);

Não é

possív

el

Não

é

possí

vel

 
      SELECT  
   

SELECT

 

4

SELECT *

FROM t7,

t8

WHERE

t7.t7_c1

=t8.t7_c

1;

SELECT *

FROM t7

INNER

JOIN t8

ON

(t7.t7_c

1=t8.t7_

*

FROM

t7

INNER

JOIN

t8

USING

Não

é

possí

vel

c1);

(t7_c1

);

T opo Sinónimos para nomes de tabelas O nome da tabela pode ser substituído por

Sinónimos para nomes de tabelas

O nome da tabela pode ser substituído por um sinónimo, como mostram os

exemplos abaixo:

Sintaxe antiga

SQL99

SELECT e.empno, e.ename, e.deptno, d.deptno, d.dname, d.loc FROM emp e, dept d WHERE e.deptno=d.deptno;

SELECT e.empno, e.ename, e.deptno, d.deptno, d.dname, d.loc FROM emp e INNER JOIN dept d ON (e.deptno=d.deptno);

A utilização de sinónimos para os nomes das tabelas apresenta as seguintes vantagens:FROM emp e INNER JOIN dept d ON ( e .deptno= d .deptno);  Ajuda a

Ajuda a distinguir as colunas que têm o mesmo nome nas duas tabelas.

O

mesmo fim pode ser atingido usando o nome da tabela;

query é mais rapidamente interpretado pela base de dados, pois esta

O

não tem duvidas de onde tem que ir buscar as colunas, pelo que poupa

processamento. Este fim também pode ser atingido recorrendo ao nome da tabela;

efectuar a junção de uma tabela com ela própria ; T opo Junção com mais de

Junção com mais de duas tabelas

A figura abaixo mostra as relações existentes entre as tabelas EMPLOYEES,

DEPARTMENTS e LOCATIONS, pertencentes ao conjunto HR:

Este relacionamento possibilita a junção entre as 3 tabelas exemplificada pelos comandos abaixo:   NATURA

Este relacionamento possibilita a junção entre as 3 tabelas exemplificada pelos comandos abaixo:

 

NATURA

Sintaxe antiga

 

ON

 

USING

L JOIN

   

SELECT

 

e.first_name

,

Não é possível porque a coluna MANAGE R_ID é comúm a Employees e a Departmen ts e nao é usada na cláusula de junção deste relacionam ento

e.last_name,

SELECT e.first_name, e.last_name, d.department_id, d.department_name, l.city, l.state_province FROM employees e, departments d, locations l WHERE e.department_id=d.dep artment_id AND d.location_id=l.locat ion_id;

SELECT

 

e.first_name,

department_i

e.last_name,

d,

d.department_id,

d.department_name,

d.department

l.city,

_name,

l.state_province

 

l.city,

FROM employees e INNER JOIN departments

l.state_prov

d

ON

ince

(e.department_id=d.depa rtment_id) INNER JOIN locations l ON (d.location_id=l.locati on_id);

FROM

employees e

INNER JOIN

departments

d

USING

(department_

   

id)

INNER JOIN

locations l

USING

(location_id

 

);

d USING (department_     id) INNER JOIN locations l USING (location_id   ) ;

Na maior parte das situações é válido o seguinte principio: se há n tabelas temos que usar n-1 condições de junção. Esta regra não é válida quando existe mais que uma relação entre duas tabelas, como no nosso exemplo, casos onde se deve aplicar o princípio abaixo;

Cada relacionamento entre duas tabelas exige uma condição de junção. Neste exemplo consideramos o único relacionamento entre LOCATIONS e DEPARTMENTS e nos vários relacionamentos existentes entre EMPLOYEES e DEPARTMENTS consideramos apenas EMP_DEPT_FK;

A condição de junção deve incluir todas as colunas usadas na junção;

A cláusula de junção e a cláusula de filtro

O facto de efectuarmos uma junção entre duas tabelas não impede que se faça um filtro das linhas. O exemplo abaixo mostra como:

 

NATURA

Sintaxe antiga

 

ON

 

USING

 

L JOIN

   

SELECT

Não é

possível

e.first_name

porque a

,

coluna

SELECT e.first_name, e.last_name, d.department_id, d.department_name FROM employees e, departments d WHERE e.department_id=d.depa rtment_id AND e.first_name like 'Jam%';

SELECT

e.last_name,

MANAGE

 

e.first_name,

e.last_name,

department_i

R_ID é

d.department_id,

d,

comúm a

d.department_name FROM employees e INNER JOIN departments

d.department

_name

Employees

e

a

d

ON

FROM

Department

(e.department_id=d.depa rtment_id) WHERE e.first_name like 'Jam%';

employees e

s

e nao é

INNER JOIN

departments

usada na

d

USING

cláusula de

   

(department_

junção

deste

id)

WHERE

e.first_name

relacionam

like '%me%';

ento

  (department_ junção deste id) WHERE e.first_name relacionam like '%me%' ; ento

Na sintaxe antiga as condições de junção e de filtro misturam-se, sendo necessária uma leitura mais atenta para as distinguir;

Na sintaxe SQL99 há uma separação clara entre condições de junção e de filtro;

separação clara entre condições de junção e de filtro; T opo A junção feita com colunas

A junção feita com colunas UNIQUE

As boas práticas recomendam que a junção entre duas tabelas seja feita entre a chave primária (PK - Primary Key) de uma e a chave estrangeira (FK - Foreign Key) da outra tabela. O motor relacional do Oracle permite que a chave primária seja substituída por uma chave alternativa. Por exemplo, em vez do número de empregado poderíamos usar o NIF (Número de Identificação Fiscal), desde que este seja único para cada empregado e tenha um valor não nulo. Para isto a base de dados requer a existência de um índice com a propriedade UNIQUE ou que seja definida a restrição UNIQUE sobre a(s) coluna(s) envolvida(s).

Junção externa

UNIQUE sobre a(s) coluna(s) envolvida(s). Junção externa O diagrama entidade relacionamento a seguir apresentado

O diagrama entidade relacionamento a seguir apresentado mostra os

relacionamentos existentes entre as tabelas EMPLOYEES e DEPARTMENTS. Considerando apenas o relacionamento "Trabalha Em" verificamos que um empregado pode não ter um departamento atribuído, assim como um departamento pode não ter empregados atribuídos. Os empregados que não têm departamento e os departamentos que não têm

empregado não aparecem no resultado de uma junção interna, mas aparecem

na junção externa. A junção externa é uma extensão da junção interna.

 Junção externa à esquerda  Junção externa à direita  Junção externa FULL (à

Junção externa à esquerda

A junção externa à esquerda estende o resultado da junção interna, pois

mostra todas as linhas que são devolvidas pela junção interna e acrescenta as linhas da tabela da esquerda que não têm correspondência na tabela da direita.

A junção envolve sempre duas tabelas, sendo a da esquerda a que primeiro

aparece no comando. O diagrama apresentado a seguir mostra como funciona

este tipo de junção:

a seguir mostra como funciona este tipo de junção: Os comandos apresentados a seguir mostram como

Os comandos apresentados a seguir mostram como fazer a junção externa à esquerda entre as tabelas EMPLOYEES e DEPARTMENTS. Esta operação vai mostrar as linhas obtidas pela junção interna, acrescida dos empregados que não têm um departamento atribuído, o que é possível porque a coluna DEPARTMENT_ID em EMPLOYEES suporta valores nulos:

Sintaxe proprietária

ON

USING

NATUR

AL

JOIN

   

SELECT

 

e.first_name

,

SELECT e.first_name, e.last_name, d.department_id, d.department_name FROM employees e, departments d WHERE e.department_id=d.depa rtment_id (+);

SELECT e.first_name, e.last_name, d.department_id, d.department_name FROM employees e LEFT OUTER JOIN departments d ON (e.department_id=d.depart ment_id);

e.last_name,

department_i

d,

Não

d.department

aplicável

_name

FROM

employees e

LEFT OUTER

JOIN

   

departments

d USING

(department_

id);

  departments d USING (department_ id); T opo Junção externa à direita A junção externa à

Junção externa à direita

A junção externa à direita funciona da mesma forma que a junção externa à esquerda, mas mostra as linhas da tabela da direita que não têm correspondência com linhas da tabela da esquerda. Este resultado pode ser obtido por uma junção à esquerda trocando a ordem das colunas. O diagrama apresentado a seguir descreve o funcionamento deste tipo de junção:

a seguir descreve o funcionamento deste tipo de junção: Os comandos apresentados a seguir mostram como

Os comandos apresentados a seguir mostram como fazer a junção externa à direita entre as tabelas EMPLOYEES e DEPARTMENTS. Esta operação vai mostrar as linhas obtidas pela junção interna, acrescida dos departamentos que não têm um empregado atribuído:

Sintaxe

   

NATURA

proprietária

ON

USING

L JOIN

SELECT

SELECT

SELECT

 

e.first_name,

Não

e.first_name,

e.last_name, d.department_id, d.department_name FROM employees e RIGHT OUTER JOIN departments d ON (e.department_id=d.department _id);

e.first_name,

aplicável

e.last_name,

e.last_name,

d.department_i

department_id,

d,

d.department_n

d.department_n

ame

ame

 

FROM employees

FROM employees

e

e, departments

RIGHT OUTER

d

JOIN

WHERE

departments d

e.department_i d (+)

USING

(department_id

=d.department_

);

id;

USING (department_id =d.department_ ); id; T opo Junção externa FULL (à esquerda e à direita) A

Junção externa FULL (à esquerda e à direita)

A junção externa FULL mostra a soma das junções externas à esquerda e à direita, como exemplificado no próximo diagrama:

e à direita, como exemplificado no próximo diagrama: Os comandos apresentados a seguir mostram como fazer

Os comandos apresentados a seguir mostram como fazer a junção externa FULL entre as tabelas EMPLOYEES e DEPARTMENTS:

Sintaxe

NATURA

proprietária

ON

USING

L JOIN

SELECT

 

SELECT

 

e.first_name,

SELECT e.first_name, e.last_name, d.department_id, d.department_name FROM employees e FULL OUTER JOIN departments d ON (e.department_id=d.department

e.first_name,

e.last_name,

e.last_name,

Não

d.department_i

department_id,

aplicável

d,

d.department_n

 

d.department_n

ame

ame

_id);

FROM employees

FROM employees

e

e, departments

FULL OUTER JOIN departments d USING (department_id );

d

WHERE

e.department_i

d

=d.department_ id (+) UNION

SELECT

 

e.first_name,

e.last_name,

d.department_i

d,

d.department_n

ame

FROM employees

e, departments

d

WHERE

e.department_i d (+)

=d.department_

id;

WHERE e.department_i d (+) =d.department_ id;  A sintaxe proprietária não permite a junção externa

A sintaxe proprietária não permite a junção externa em simultâneo à esquerda e à direita, pelo que recorremos ao operador UNION que faz a junção vertical dos dois conjuntos resultado;

O recurso ao operador UNION na sintaxe proprietária força a execução de 2 queries para resolver o problema, ao contrário dos exemplos com sintaxe SQL99 que resolvem com um único query;

Junção Vertical - Operadores sobre conjuntos

único query; Junção Vertical - Operadores sobre conjuntos O SQL disponibiliza três operadores que permitem a

O SQL disponibiliza três operadores que permitem a partir de dois conjuntos produzir um terceiro. Estes operadores actuam sobre as colunas das tabelas de origem, produzindo uma Junção Vertical:

UNIÃO

Estes operadores permitem obter um único conjunto resultado a partir de dois conjuntos iniciais. São úteis na junção de diferentes consultas que se refiram a tabelas diferentes mas que tenham colunas com o mesmo tipo de dados. A sua utilizaçãoo segue as seguintes regras:

1. As duas instruções SELECT têm que seleccionar o mesmo número de colunas;

2. As colunas correspondentes têm que ser do mesmo tipo de dados;

3. As linhas duplicadas são eliminadas pelo operador UNION. Se usarmos UNION ALL os duplicados não são eliminados, o que poupa uma operação de SORT;

4. Os nomes de coluna da primeira consulta aparecem no resultado;

5. A cláusula ORDER BY aparece no fim da instrução. Se as colunas correspondentes dos diferentes SELECT's tiverem nomes diferentes, a referêcia à(s) coluna(s) deverá ser feita por número de posição;

6. As instruções SELECT são executadas de cima para baixo;

7. Se forem utilizados vários operadores de conjunto é possivel usar parentesis para definir prioridades de execução;

UNIÃO (UNION)

O operador UNION permite obter a reunião de dois conjuntos:

O operador UNION permite obter a reunião de dois conjuntos: O comando abaixo apresenta os nomes

O comando abaixo apresenta os nomes e salários dos empregados das tabelas

EMP e EMPLOYEES. São duas consultas unidas numa única.

select ename, sal from emp UNION select first_name, salary from employees;

O comando UNION elimina automaticamente as linhas repetidas. Se pretendermos que estas apareçam teremos que utilizar UNION ALL:

select job from emp UNION select job_id from employees;

JOB

----------

AC_ACCOUNT

AC_MGR

AD_ASST

AD_PRES

AD_VP

ANALYST

CLERK

FI_ACCOUNT

FI_MGR

HR_REP

IT_PROG

MANAGER

MK_MAN

MK_REP

PRESIDENT

PR_REP

PU_CLERK

PU_MAN

SALESMAN

SA_MAN

SA_REP

SH_CLERK

ST_CLERK

ST_MAN

24 rows selected

select job from emp UNION ALL select job_id from employees;

JOB

----------

CLERK

SALESMAN

SALESMAN

MANAGER

SALESMAN

MANAGER

MANAGER

ANALYST

PRESIDENT

SALESMAN

CLERK

CLERK

ANALYST CLERK AC_ACCOUNT AC_MGR AD_ASST AD_PRES AD_VP AD_VP FI_ACCOUNT FI_ACCOUNT FI_ACCOUNT FI_ACCOUNT
ANALYST
CLERK
AC_ACCOUNT
AC_MGR
AD_ASST
AD_PRES
AD_VP
AD_VP
FI_ACCOUNT
FI_ACCOUNT
FI_ACCOUNT
FI_ACCOUNT
FI_ACCOUNT
FI_MGR
HR_REP
IT_PROG
IT_PROG
IT_PROG
IT_PROG
IT_PROG
MK_MAN
MK_REP
PR_REP
PU_CLERK
PU_CLERK
PU_CLERK
PU_CLERK
PU_CLERK
PU_MAN
SA_MAN
SA_MAN
SA_MAN
SA_MAN
SA_MAN
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP
SA_REP SA_REP SA_REP SH_CLERK SH_CLERK SH_CLERK SH_CLERK SH_CLERK SH_CLERK SH_CLERK SH_CLERK SH_CLERK SH_CLERK
SA_REP
SA_REP
SA_REP
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
SH_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_CLERK
ST_MAN
ST_MAN
ST_MAN
ST_MAN
ST_MAN
121 rows selected
ST_MAN ST_MAN ST_MAN ST_MAN ST_MAN 121 rows selected  O operador UNION ALL não respeita a

O operador UNION ALL não respeita a teoria de conjuntos, pois permite a repetição de elementos. Foi criado por uma questão de

desempenho, já que evita ao motor de base de daos as operações ordenação e filtro. Deve ser usado quando não faça difrença trabalhar com elementos repetidos;

INTERSECÇÃO (INTERSECT)

O operador INTERSECT permite obter a intersecção entre dois conjuntos:

permite obter a intersecção entre dois conjuntos: O comando abaixo permite listar os salários que existem

O comando abaixo permite listar os salários que existem em EMP e em

EMPLOYEES:

select sal from emp INTERSECT select salary from employees;

SAL

----------------------

3000

1 rows selected

select sal from emp INTERSECT select salary from employees; SAL ---------------------- 3000 1 rows selected

DIFERENÇA (MINUS)

O operador MINUS permite obter a diferença entre dois conjuntos:

O comando abaixo permite listar os salários que estão em EMP e não estão em

O comando abaixo permite listar os salários que estão em EMP e não estão em EMPLOYEES:

select sal from emp MINUS select salary from employees;

SAL

----------------------

800

950

1100

1250

1300

1500

1600

2450

2850

2975

5000

11 rows selected

Exercícios sobre junção de tabelas

11 rows selected Exercícios sobre junção de tabelas 1. Liste todos os empregados e respectivos nomes

1. Liste todos os empregados e respectivos nomes de departamento, por ordem do nome de departamento;

2. Liste o nome, número e nome de departamento de todos os empregados;

3. Liste o nome, departamento e localidade do departamento dos empregados cujo salário mensal seja superior a 1500;

4. Produza uma lista que mostre o nível salarial (GRADE) de cada empregado;

5. Produza uma lista dos empregados com nível salarial 3;

6. Mostre todos os empregados de Dallas (Dept Loc);

8. Liste o nome, função, salário anual, número de departamento, nome de departamento e nível salarial (grade) para os empregados que ganham mais de 36000 por ano (14 vezes o salário mais a comissão) ou que sejam empregados de escritório (CLERK);

9. Liste todos os departamentos que não têm empregados;

10.Liste o nome e número de empregado juntamente com o nome e número do seu manager; 11.Modifique a solução da questão 10 de forma a visualizar KING que não tem manager; 12.Encontre o departamento que contratou funcionários na primeira metade de 1981 e na primeira metade de 1982; 13.Encontre todos os empregados que entraram para a empresa antes do

seu manager; 14.Encontre um outro método de consulta para a questãoa 9 utilizando o operador MINUS.

Soluções dos exercícios sobre junção de tabelas

15.

16.

1.

17.Solução usando a sintaxe tradicional:

15. 16. 1. 17.Solução usando a sintaxe tradicional: 18. select e.ename, e.deptno, d.dname 19. from emp

18. select e.ename, e.deptno, d.dname

19. from emp e, dept d

20. where e.deptno=d.deptno

21. order by d.dname;

22.Solução usando a sintaxe SQL99:

23. select e.ename, e.deptno, d.dname

24. from emp e

25. inner join dept d on (e.deptno=d.deptno)

26. order by d.dname;

27.

28. 2.

29.Solução usando a sintaxe tradicional:

30. select e.ename, d.deptno, d.dname

31. from emp e, dept d

32. where e.deptno=d.deptno;

33.Solução usando a sintaxe SQL99:

34. select e.ename, d.deptno, d.dname

35. from emp e

36. inner join dept d on (e.deptno=d.deptno);

37.

38. 3.

39.Solução usando a sintaxe tradicional:

41.

from emp e, dept d

42. where e.deptno = d.deptno

43. and sal > 1500;

44.Solução usando a sintaxe SQL99:

45. select e.ename,d.dname,d.loc

46. from emp e

47. inner join dept d on (e.deptno = d.deptno)

48. where sal > 1500;

49.

50. 4.

51.Solução usando a sintaxe tradicional:

52. select ename, job, sal, grade

53. from emp, salgrade

54. where sal between salgrade.losal and salgrade.hisal;

55.Solução usando a sintaxe SQL99:

56. select ename, job, sal, grade

57. from emp

58. inner join salgrade on (sal between salgrade.losal and salgrade.hisal);

59.

60. 5.

61.Solução usando a sintaxe tradicional:

62. select ename, job, sal, grade

63. from emp, salgrade

64. where sal between salgrade.losal and salgrade.hisal

65. and grade = 3;

66.Solução usando a sintaxe SQL99:

67. select ename, job, sal, grade

68. from emp

69. inner join salgrade on (sal between salgrade.losal and salgrade.hisal)

70. where grade = 3;

71.

72. 6.

73.Solução usando a sintaxe tradicional:

74. select emp.ename, emp.sal, dept.loc

75. from emp, dept

76. where emp.deptno=dept.deptno

77. and dept.loc = 'DALLAS';

78.Solução usando a sintaxe SQL99:

79. select emp.ename, emp.sal, dept.loc

80. from emp

81. inner join dept on (emp.deptno=dept.deptno)

82. where dept.loc = 'DALLAS';

83.

84. 7.

85.Solução usando a sintaxe tradicional:

86. select e.ename, e.job, e.sal, s.grade, d.dname

87. from emp e, salgrade s, dept d

88. where e.sal between s.losal and s.hisal

89. and e.deptno=d.deptno

90. and e.job !='CLERCK'

91. order by e.sal desc;

92.Solução usando a sintaxe SQL99:

93. select e.ename, e.job, e.sal, s.grade, d.dname

94. from emp e

95. inner join salgrade s on (e.sal between s.losal and s.hisal)

96. inner join dept d on (e.deptno=d.deptno)

97. where e.job != 'CLERCK'

98. order by e.sal desc;

99.

100. 8.

101. Solução usando a sintaxe tradicional:

102. select e.ename, e.job, e.sal*14+nvl(e.comm,0), d.deptno, d.dname, s.grade

103. from emp e, salgrade s, dept d

104. where e.sal between s.losal

105. and s.hisal and e.deptno=d.deptno

106. and (e.sal*14+nvl(e.comm,0) > 36000 or e.job = 'CLERK');

107. Solução usando a sintaxe SQL99:

108. select e.ename, e.job, e.sal, s.grade, d.dname

109. from emp e

110. inner join salgrade s on (e.sal between s.losal and s.hisal)

111. inner join dept d on (e.deptno=d.deptno)

112. where e.job != 'CLERCK'

113. order by e.sal desc;

114.

115. 9.

116. Solução usando a sintaxe tradicional. O operador (+) coloca-se

sempre do lado fraco, isto é, do lado onde pode haver uma linha NULL:

117. select d.deptno, d.dname

118. from emp e, dept d

119. where e.deptno (+) = d.deptno

120. and e.ename is null;

121. Solução usando a sintaxe SQL99:

122. select d.deptno, d.dname

123. from emp e

124. right outer join dept d on (e.deptno = d.deptno)

125. where e.ename is null;

126.

127. 10.

128. Solução usando a sintaxe tradicional:

129. select e.empno as empregado_numero, e.ename as empregrado_nome,

130. m.empno as manager_numero, m.ename as manager_nome

131. from emp e, emp m

132. where e.mgr = m.empno;

133. Solução usando a sintaxe SQL99:

134. select e.empno as empregado_numero, e.ename as empregrado_nome,

135. m.empno as manager_numero, m.ename as manager_nome

136. from emp e

137. inner join emp m on (e.mgr = m.empno)

139.

11.

140. Solução usando a sintaxe tradicional. O operador (+) coloca-se

sempre do lado fraco, isto é, do lado onde pode haver uma linha NULL.

141. select e.ename,e.empno,e.mgr,m.ename,m.empno

142. from emp e, emp m

143. where e.mgr=m.empno (+);

144. Solução usando a sintaxe SQL99:

145. select e.ename,e.empno,e.mgr,m.ename,m.empno

146. from emp e

147. left outer join emp m on (e.mgr=m.empno (+));

148.

149. 12.

150. Solução usando a sintaxe tradicional:

151. select e.deptno, d.dname

152. from emp e, dept d

153. where e.deptno=d.deptno

154. and

e.hiredate between to_date('1981-01-01','YYYY-MM-DD') and

to_date('1981-06-30','YYYY-MM-DD')

155. intersect

156. select e.deptno, d.dname

157. from emp e, dept d

158. where e.deptno=d.deptno

159. and

hiredate between to_date('1982-01-01','YYYY-MM-DD') and

to_date('1982-06-30','YYYY-MM-DD');

160. Usando sintaxe SQL99

161. select e.deptno, d.dname

162. from emp e

163. inner join dept d on (e.deptno=d.deptno)

164. where e.hiredate between to_date('1981-01-01','YYYY-MM-DD') and

to_date('1981-06-30','YYYY-MM-DD')

165. intersect

166. select e.deptno, d.dname

167. from emp e

168. inner join dept d on (e.deptno=d.deptno)

169. where

hiredate between to_date('1982-01-01','YYYY-MM-DD') and

to_date('1982-06-30','YYYY-MM-DD');

170.

171. 13.

172. Solução usando a sintaxe tradicional:

173. select e.ename as empregado_nome, e.hiredate as empregado_data,

174. m.ename as manager_nome, m.hiredate as manager_data

175. where e.mgr=m.empno

176. and e.hiredate > m.hiredate;

177. Usando sintaxe SQL99

178. select e.ename as empregado_nome, e.hiredate as empregado_data,

179. m.ename as manager_nome, m.hiredate as manager_data

180. from emp e

181. inner join emp m on (e.mgr=m.empno)

182. and e.hiredate > m.hiredate;

183.

184. 14.

185. Retirar à lista dos departamentos aqueles que têm empregados.

186. Solução usando a sintaxe tradicional:

187. select deptno, dname

188. from dept

189. minus

190. select e.deptno, d.dname

191. from emp e, dept d

192. where e.deptno=d.deptno;

193. Usando sintaxe SQL99

194. select deptno, dname

195. from dept

196. minus

197. select e.deptno, d.dname

198. from emp e

199. inner join dept d on (e.deptno=d.deptno);

Subconsultas simples e correlacionadas

(e.deptno=d.deptno); Subconsultas simples e correlacionadas Uma subconsulta é uma instrução SELECT que está

Uma subconsulta é uma instrução SELECT que está encadeada dentro de outra instrução SELECT. A consulta interior é designada por selecção interna e é executada em primeiro lugar, sendo o seu resultado utilizado para completar a consulta principal ou externa. A utilização de subconsultas permite construir comandos potentes a partir de comandos mais simples.

Na construção de subconsultas devem ser seguidas as seguintes linhas de orientação:

A consulta interna deverá ser colocada entre parentisis e terá que estar no lado direito da condição;

Desde a versão 8.1.7 do motor Oracle que as subconsultas podem ter uma cláusula ORDER BY;

As subconsultas podem devolver uma ou mais linhas, uma ou mais colunas. Se devolverem várias colunas então terão que estar pela mesma ordem que as colunas que apareçam na cláusula de condição da consulta externa (ou principal). O tipo de dados e o número de colunas têm também que corresponder;

As subconsultas podem utilizar operadores lógicos, operadores de SQL, operadores ANY e ALL e operadores de conjunto;

As subconsultas podem ser utilizadas em instruções de SELECT, UPDATE, DELETE, INSERT e CREATE TABLE;

Existem dois tipos de subconsultas:

Simples

Suponha que pretende encontrar o(s) empregado(s) que ganha(m) o salário mais baixo na empresa, desconhecendo a quantia em causa. O problema pode resolver-se em dois passos:

Encontrar o salário mais baixo;

Encontrar o(s) empregado(s) que ganha(m) o salário mais baixo;

Para o primeiro passo usamos a consulta abaixo:

select min(sal) from emp;

MIN(SAL)

----------------------

800

1

rows selected

Para o segundo passo usamos a consulta abaixo:

select ename, job, sal from emp where sal = 800;

 

ENAME

JOB

SAL

---------- --------- ----------------------

SMITH

CLERK

800

1

rows selected

Os dois queries podem ser juntos num só, usando uma subconsulta:

select ename, job, sal from emp where sal = (select min(sal) from emp);

ENAME

JOB

SAL

---------- --------- ----------------------

SMITH

CLERK

800

1 rows selected

A consulta interior é executada em primeiro lugar produzindo um resultado

(800). O bloco externo é depois executado, utilizando o valor devolvido pela

consulta interna para completar a sua condição de pesquisa.

O exemplo abaixo procura todos os empregados que executam a mesma

função que BLAKE:

select ename,job from emp

where job = (select job from emp where ename = 'BLAKE');

EENAME

JOB

---------- ---------

JONES

MANAGER

BLAKE

MANAGER

CLARK

MANAGER

3 rows selected

BLAKE MANAGER CLARK MANAGER 3 rows selected  Na consulta anterior o programador corre um risco:

Na consulta anterior o programador corre um risco: a consulta interna pesquisa por nome, que não é uma coluna UNIQUE e portanto não há garantias de que devolva apenas um valor. Se devolver mais que um valor a consulta toda dá um erro, por causa da comparação feita com =;

Para resolver este problema podemos recorrer ao operador ANY, que será visto mais à frente;

Subconsultas correlacionadas

Uma subconsulta correlacionada é executada de forma diferente da subconsulta simples. Nestas consultas o subquery precisa de um dado que vem do query principal, pelo que o SELECT interno é executado tantas vezes quantas as linhas que são processadas no query principal.

A lista abaixo contem os passos necessários para executar uma consulta

correlacionada:

Obter uma linha candidata a partir da consulta externa;

Executar a consulta interna utilizando o valor da linha candidata;

Utilizar o valor ou valores resultantes da consulta interna para qualificar ou desqualificar a linha candidata;

Repetir para a próxima linha até que não haja mais linhas candidatas;

A consulta abaixo pretende encontrar os empregados que ganham um salário

superior ao salário médio do respectivo departamento:

select e1.empno, e1.ename, e1.sal, e1.deptno from emp e1 where e1.sal > (select avg(e2.sal) from emp e2 where e2.deptno = e1.deptno);

EMPNO

---------------------- ---------- ---------------------- -------------

ENAME

SAL

DEPTNO

---------

7499

ALLEN

1600

30

7566

JONES

2975

20

7698

BLAKE

2850

30

7788

SCOTT

3000

20

7839

KING

5000

10

7902

FORD

3000

20

6 rows selected

10 7902 FORD 3000 20 6 rows selected  Para identificar que se trata de uma

Para identificar que se trata de uma subconsulta correlacionada é preciso reparar na utilização de uma coluna da tabela do SELECT externo na cláusula WHERE do SELECT interno;

O pseudónimo de tabela é utilizado para evitar ambiguidade nos nomes das colunas, pois tanto a consulta interna como a externa usam a mesma tabela;

Subconsulta que devolve várias linhas - operadores do SQL

Subconsulta que devolve várias linhas - operadores do SQL Os exemplos de subconsulta que vimos até

Os exemplos de subconsulta que vimos até agora devolvem apenas uma linha. Mas uma subconsulta pode devolver várias linhas, o que obriga a consulta externa a ter cuidados especiais e a recorrer aos operadores do SQL:

IN

ALL

EXISTS

IN

Quando a subconsulta devolve várias linhas o operador IN pode ser usado para validar se uma linha da consulta externa está presente no conjunto criado pela subconsulta. Devolve TRUE se o(s) valor(es) usado(s) na consulta externa está(ão) incluído(s) no conjunto devolvido pela consulta interna. Este operador pode ser negado com NOT.

Suponha que pretende determinar os empregados que ganham o salário mais baixo em cada função, usando a tabela EMPLOYEES. A consulta abaixo tenta responder a esta pergunta, mas sem sucesso.

abaixo tenta responder a esta pergunta, mas sem sucesso. select first_name,salary,job_id from employees where salary

select first_name,salary,job_id from employees where salary in (select min(salary) from employees group by job_id);

 

FIRST_NAME

SALARY

JOB_ID

-------------------- ---------------------- ----------

Nandita

4200

SH_CLERK

Diana

4200

IT_PROG

Shelley

12000

AC_MGR

Alberto

12000

SA_MAN

Nancy

12000

FI_MGR

William

8300

AC_ACCOUNT

Kevin

5800

ST_MAN

Ellen

11000

SA_REP

Gerald

11000

SA_MAN

Den

11000

PU_MAN

Jennifer

4400

AD_ASST

Lex

17000

AD_VP

Neena

17000

AD_VP

Randall

2500

SH_CLERK

Martha

2500

SH_CLERK

Peter

2500

ST_CLERK

Joshua

2500

ST_CLERK

James

2500

ST_CLERK

Karen

2500

PU_CLERK

Luis

6900

FI_ACCOUNT

Clara

10500

SA_REP

Eleni

10500

SA_MAN

Michael

13000

MK_MAN

Hermann

10000

PR_REP

Harrison

10000

SA_REP

Janette

10000

SA_REP

Peter

10000

SA_REP

Steven

24000

AD_PRES

Sundita

6100

SA_REP

Pat

6000

MK_REP

Bruce

6000

IT_PROG

TJ

2100

ST_CLERK

Susan

6500

HR_REP

Shanta

6500

ST_MAN

34 rows selected

HR_REP Shanta 6500 ST_MAN 34 rows selected  O resultado obtido não está correcto pois a

O resultado obtido não está correcto pois a consulta nãogarante que o salário mínimo encontrado na subconsulta se refere ao departamento para o qual trabalha o empregado da consulta externa;

O salário mínimo da função SA_MAN é 10500. O empregado Alberto, com a função SA_MAN ganha 12000, que é acima do mínimo, mas aparece no resultado da consulta. Isto porque o seu salário é igual ao mínimo da função FI_MGR;

A forma de associar a função ao salário mínimo é devolver e comparar o par

de valores, como no exemplo abaixo:

select first_name,salary,job_id from employees where (job_id,salary) in (select job_id,min(salary) from employees group by job_id);

FIRST_NAME

SALARY

JOB_ID

-------------------- ---------------------- ----------

Diana

4200

IT_PROG

Shelley

12000

AC_MGR

William

8300

AC_ACCOUNT

Kevin

5800

ST_MAN

Den

11000

PU_MAN

Jennifer

4400

AD_ASST

Neena

17000

AD_VP

Lex

17000

AD_VP

Martha

2500

SH_CLERK

Randall

2500

SH_CLERK

Luis

6900

FI_ACCOUNT

Nancy

12000

FI_MGR

Karen

2500

PU_CLERK

Eleni

10500

SA_MAN

Michael

13000

MK_MAN

Hermann

10000

PR_REP

Steven

24000

AD_PRES

Sundita

6100

SA_REP

Pat

6000

MK_REP

TJ

2100

ST_CLERK

Susan

6500

HR_REP

21 rows selected

ST_CLERK Susan 6500 HR_REP 21 rows selected T opo ANY (SOME) O operador ANY (e o

ANY (SOME)

O operador ANY (e o seu sinónimo SOME) permite a uma consulta externa

fazer comparações usando < ou > com os elementos de um conjunto devolvido pela subconsulta. Este operador devolve TRUE se uma das linhas do conjunto satisfaz a condição, ou seja, devolve FALSE se nenhuma satisfaz a condição. Este operador pode ser negado com NOT.

A consulta abaixo devolve os empregados que ganham mais que algum

empregado do departamento 30. Isto é o mesmo que afirmar que procuramos os que ganham mais que o salário mínimo do departamento 30.

select ename, sal, job, deptno from emp where sal > ANY (select distinct sal from emp where deptno=30);

 

ENAME

SAL

JOB

DEPTNO

---------- ---------------------- --------- ----------------------

KING

5000

PRESIDENT 10

FORD

3000

ANALYST

20

SCOTT

3000

ANALYST

20

JONES

2975

MANAGER

20

BLAKE

2850

MANAGER

30

CLARK

2450

MANAGER

10

ALLEN

1600

SALESMAN 30

TURNER

1500

SALESMAN 30

MILLER

1300

CLERK

10

WARD

1250

SALESMAN 30

MARTIN

1250

SALESMAN 30

ADAMS

1100

CLERK

20

12 rows selected

 
ADAMS 1100 CLERK 20 12 rows selected    A comparação '= ANY' pode ser usada,

A comparação '= ANY' pode ser usada, mas é equivalente a IN;

Ao utilizar ANY é frequente recorrer à cláusula DISTINCT, para evitar linhas repetidas e assim tornar a avaliação da expressão lógica mais eficiente;

ALL

O operador ALL permite a uma consulta externa fazer comparações usando <

ou > com os elementos de um conjunto devolvido pela subconsulta. Este operador devolve TRUE se todas as linhas do conjunto satisfazem a condição, ou seja, devolve FALSE se alguma linha não a satisfaz. Este operador pode ser negado com NOT.

A consulta abaixo devolve os empregados que ganham mais que todos os

empregados do departamento 30. Isto é o mesmo que afirmar que procuramos

select ename, sal, job, deptno from emp where sal > ALL (select distinct sal from emp where deptno=30);

 

ENAME

SAL

JOB

DEPTNO

---------- ---------------------- --------- ----------------------

JONES

2975

MANAGER

20

SCOTT

3000

ANALYST

20

KING

5000

PRESIDENT 10

FORD

3000

ANALYST

20

4

rows selected

 

EXISTS

O operador EXISTS permite à consulta externa verificar se a consulta interna

devolveu alguma linha. Não se preocupa com o valor das linhas, mas sim com a cardinalidade do conjunto. Devolve TRUE se a cardinalidade for superior a

0 (zero) e FALSE caso seja igual a 0 (zero). Este operador pode ser negado com NOT.

O exemplo abaixo procura os empregados que tenham pelo menos um

subordinado:

select m.empno,m.ename,m.job,m.deptno from emp m where exists (select e.empno from emp e where e.mgr=m.empno)

 

EMPNO

ENAME

JOB

DEPTNO

---------------------- ---------- --------- ----------------------

7902

FORD

ANALYST

20

7698

BLAKE

MANAGER

30

7839

KING

PRESIDENT 10

7566

JONES

MANAGER

20

7788

SCOTT

ANALYST

20

7782

CLARK

MANAGER

10

6

rows selected

20 7782 CLARK MANAGER 10 6 rows selected  Temos uma subconsulta correlacionada, onde o SELECT

Temos uma subconsulta correlacionada, onde o SELECT externo selecciona os managers (m - tabela manager) enquanto o SELECT interno selecciona os empregados desse manager (e - tabela empregado);

O exemplo abaixo procura todos os departamentos que não possuem

empregados:

select d.deptno, d.dname from dept d where not exists (select deptno from emp e where e.deptno=d.deptno);

DEPTNO

DNAME

---------------------- --------------

40

OPERATIONS

1

rows selected

-------------- 40 OPERATIONS 1 rows selected  Recorremos uma subconsulta correlacionada. A conculta

Recorremos uma subconsulta correlacionada. A conculta externa percorre todos os departamentos. A consulta interna valida se o departamento tem empregados.

O query interno necessita devolver um valor que não tem que ser a coluna que

está em causa. O exemplo anterior pode ser substituído por este:

select d.deptno, d.dname from dept d where not exists (select 1 from emp e where e.deptno=d.deptno);

DEPTNO

DNAME

---------------------- --------------

40

OPERATIONS

1

rows selected

Uma consulta ao dicionário de dados mostra que o relacionamento entre as tabelas EMP e DEPT não está assegurado por uma restrição definida no motor da base de dados. Isto significa que é possível que exista um empregado que trabalhe num departamento que não esteja definido na tabela DEPT. A consulta abaixo pesquisa isso:

select e.empno, e.ename, e.deptno from emp e where not exists (select deptno from dept where dept.deptno=e.deptno);

EMPNO

ENAME

DEPTNO

---------------------- ---------- ----------------------

0

rows selected

Subconsulta e cláusulas da instrução SELECT

Subconsulta e cláusulas da instrução SELECT Uma subconsulta pode ser colocada em vários pontos da instrução

Uma subconsulta pode ser colocada em vários pontos da instrução SELECT:

WHERE

HAVING

FROM

SELECT

Subconsulta na cláusula WHERE

Nos exemplos apresentados até aqui a subconsulta aparece na cláusula WHERE.

O exemplo abaixo procura todos os empregados que executam a mesma

função que BLAKE (subconsulta simples):

select ename,job from emp where job = (select job from emp where ename = 'BLAKE');

EENAME

JOB

---------- ---------

JONES

MANAGER

BLAKE

MANAGER

CLARK

MANAGER

3 rows selected

A consulta abaixo procura os empregados que ganham um salário superior ao

salário médio do respectivo departamento (subconsulta correlacionada):

select e1.empno, e1.ename, e1.sal, e1.deptno from emp e1 where e1.sal > (select avg(e2.sal) from emp e2 where e2.deptno = e1.deptno);

 

EMPNO

ENAME

SAL

DEPTNO

---------------------- ---------- ---------------------- -------------

---------

7499

ALLEN

1600

30

7566

JONES

2975

20

7698

BLAKE

2850

30

7788

SCOTT

3000

20