terça-feira, 14 de agosto de 2012

Trabalhando com JOIN no Oracle 10g


Neste estudo vamos trabalhar com JOIN, LEFT JOIN e RIGHT JOIN nas consultas. Qual o objetivo desses comandos? Na criação de banco de dados relacionais é muito comum relacionarmos tabelas através da CONSTRAINT FOREIGN KEY (chave estrangeira). Através das cláusulas JOIN podemos obter valores conjuntos das tabelas vinculadas. Talvez isso fique mais claro a partir dos exemplo práticos adiante.
Os comandos apresentados basear-se-ão no modelo apresentado abaixo:


Para mais informações sobre esse modelo e o diagrama apresentado, clique aqui.

Inserindo valores no banco
Para realizarmos os exemplos seguintes, será interessante que a base esteja alimentada. Para isso, utilize os seguintes comandos:

insert into bancos (descricao) values ('Banco Real');
insert into bancos (descricao) values ('Banco do Brasil');
insert into tipo_cliente (descricao) values ('Microempresa'); insert into tipo_cliente (descricao) values ('Empresa de Pequeno Porte'); insert into tipo_cliente (descricao) values ('Empresa de Médio Porte');

insert into clientes (nome,tipo,banco) values ('Orange Technology',1,1); insert into clientes (nome,tipo,banco) values ('Infobrasil LTDA',2,2);
insert into clientes (nome,tipo,banco) values ('Empresa Jr.',3,null);
 
União regular
A união regular entre tabelas apresenta o tipo de associação mais simples pelo SELECT. Existem quatro formas de construir esse tipo de pesquisa:

    Através do WHERE:
   
O comando abaixo irá associar as tabelas "clientes" e "tipo_clientes".

    select
        clientes.nome, tipo_cliente.descricao
    from
        clientes, tipo_cliente
    where
        clientes.tipo = tipo_cliente.id;

   Através do NATURAL JOIN:
  
O comando NATURAL JOIN realiza a definição das associações de acordo com a CONSTRAINT estabelecida na criação das tabelas.

   
select
        clientes.nome, tipo_cliente.descricao
    from
        clientes natural join tipo_cliente;
      
    Através do JOIN (com USING):
  
Este é um caso particular de JOIN que só é possível de ser utilizado quando ambos os campos (chave primária de "tipo_cliente" e chave estrangeira de "clientes") possuem o mesmo nome. Em nosso exemplo, isso não ocorre, portanto, este comando não funcionará. Supondo que o campo "id" da tabela "tipo_cliente" fosse definido com o nome "tipo", o comando abaixo seria correto.

   
select
        clientes.nome, tipo_cliente.descricao
    from
        clientes join tipo_cliente using (tipo);


    Através do JOIN (com ON):
  
Particularmente eu prefiro este modelo, pois podemos definir explicitamente o nome dos campos que serão associados através da sintaxe ON. Este é um bom exemplo para nosso modelo (diferente do exemplo anterior), pois as tabelas são ligadas por campos de nomes distintos.

    select
        clientes.nome, tipo_cliente.descricao
    from
        clientes join tipo_cliente
    on clientes.tipo = tipo_cliente.id;
 
Em todos os casos apresentados (com exceção do terceiro caso - USING) a saída será:



O que temos de errado com esse JOIN?
Como você pode observar, em todos os casos, a saída foi encontrada. Isso ocorre porque em todos os casos da associação entre as tabelas "clientes" e "tipo_cliente", os respectivos campos "tipo" e "id" assumem os mesmos valores (a regra FOREIGN KEY e NOT NULL garante isso). Agora imagine o que ocorreria se aplicássemos o JOIN comum na relação entre "clientes" e "bancos".

    select
        clientes.nome, bancos.descricao
    from clientes join bancos
    on clientes.banco = bancos.id;
 
O resultado seria:


O que há de errado neste resultado? Lembre-se que inserimos três registros de "clientes", sendo que o cliente "Empresa Jr." NÃO possui banco (seu INSERT definiu o valor NULL para o código do banco). Porque isso ocorre? A regra do SELECT é clara: traga-me todos os registros onde o "id" da tabela "bancos" for exatamente igual ao "banco" da tabela "clientes". Como o cliente "Empresa Jr." possui o valor NULL em "banco" e não existe registrado um banco onde o "id" é nulo, este resultado não é apresentado. Como vamos resolver essa situação?

Utilizando o LEFT OUTER JOIN
Através desse comando, iremos dizer ao banco para listar dados das duas tabelas ("clientes" e "bancos") sendo que, utilize a tabela da esquerda da regra (neste caso, a tabela "clientes") como referência. Ou seja, todos os clientes deverão ser mostrados mesmo que não exista um registro em "bancos" correspondente ao valor da coluna "banco".

    select
        clientes.nome, bancos.descricao
    from clientes left outer join bancos
    on clientes.banco = bancos.id;

Vualá! Nosso resultado é:


Muito bem. A regra RIGHT OUTER JOIN funciona da mesma forma.

Utilizando o RIGHT OUTER JOIN
Em nosso exemplo, como a tabela "bancos" fica à direita da regra, significa que o comando vai priorizar os códigos existentes da mesma. Como o "banco" da
"Empresa Jr." está valorado com NULL, e NÃO existe "bancos" com esse "id", essa tupla não será exibida.

    select
        clientes.nome, bancos.descricao
    from clientes right outer join bancos
    on clientes.banco = bancos.id;

Note que, como esperado, o resultado apresentado é igual ao da regra JOIN comum.

Facilidades do SELECT no Oracle
O Oracle apresenta uma diretiva que facilita a condição de LEFT JOIN e RIGHT JOIN. Podemos colocar o comando "(+)" no lado da WHERE em que o valor do campo poderá ser NULL. Por exemplo, para o comando


    select
        clientes.nome, bancos.descricao
    from clientes left outer join bancos
    on clientes.banco = bancos.id;

Obtemos o mesmo resultado utilizando a sintaxe:

    select
        clientes.nome, bancos.descricao
    from
        clientes, bancos
    where
        clientes.banco = bancos.id (+);
  
Este comando indica que o valor do "id" de "bancos" poderá ser associado com um valor NULL do campo "banco" de "clientes". Em ambos os casos, o resultado será:



Bom, é isso ai!
"Às vezes é melhor ser o rabo da baleia que a cabeça da formiga.", Eike Batista
Abraços, Guilherme Pontes.

Nenhum comentário:

Postar um comentário