Uma das grandes vantagens do X++ como linguagem para um ERP são suas funcionalidades de acesso a dados integradas a própria linguagem. Isto simplifica bastante o acesso à camada de dados. Mesmo assim existem muitas formas de alcançar os mesmos objetivos, umas mais adequadas que outras. Neste post vou analisar algumas destas alternativas.
A estrutura mais utilizada de acesso aos dados de uma tabela é o while select. N exemplo abaixo seleciono e processo todos os clientes, contidos na tabela CustTable, que pertencem ao grupo “INTER-PR”.
Estendendo este código posso trazer as vendas abertas para estes clientes. O exemplo abaixo mostra isto, porém de uma forma pouco performática. Para cada cliente você faz um novo select na tabela de pedidos. Para uma base de 500 clientes, são 501 acessos ao banco de dados.
O código abaixo mostra uma solução usando um join entre as duas tabelas. O resultado é o mesmo, mas o acesso ao banco de dados é feito de uma vez. O que torna a solução mais performática.
Outro problema muito comum é listar todos os clientes que têm ordens de venda em aberto. Uma solução que pode parecer razoável é esta abaixo. Para cada cliente verifico se existe uma ordem aberta para ele.
Existem dois pontos fracos nesta solução: O primeiro select traz todos os clientes, sem filtrar nada. Depois disto, para cada cliente, um select é realizado na tabela de ordens de venda. Novamente um join é o mais adequado para este caso. Porém, neste caso, o ideal é fazer um tipo especial de join, que o exists join.
Neste caso, o exists join tem uma grande vantagem sobre um join comum: Não traz todas as ordens de vendas de cada cliente. Com isto o resultado do select é menor (leia-se: quantas linhas retornam). Além disto, a instância da tabela de ordens de compras não é carregada, economizando memória.
Este tipo de join tem seu inverso, que é o notexists. O comando também é conhecido como “minus” em SQL, pois trazem as linhas da tabela de cliente MENOS os clientes que estão na tabela de ordens de venda. Este é o resultado do código abaixo.
Utilizando o notexists temos que tomar o seguinte cuidado. As cláusulas where referentes à tabela de clientes devem ser escritas logo abaixo do select. Já as cláusulas referentes ao join entre as tabelas ficam no final do comando. Se eu quiser, por exemplo, filtrar os clientes que estão em São Paulo, tenho a query abaixo. Dois where no mesmo select não é comum em SQL, mas a leitura é bem intuitiva: Quero buscar os clientes que estão em São Paulo (primeiro select) e que não têm ordens de venda (o join).
Se você tentar colocar a cláusula do cliente no final, junto com as outras, verá que o resultado é o inverso, a query trará os cliente que não estão em São Paulo, pois a cláusula está relacionada ao notexists.
Como conclusão, seguem algumas dicas para identificar qual a melhor solução:
- Se dentro do select while você está fazendo testes com campos da tabela ou buscando informações de outras tabelas, também usando informações da tabela, verifique se um join não pode resolver este problema.
- Se você está fazendo um join, mas a segunda tabela só é utilizada como filtro para o select, verifique se é possível utilizar o comando exists ou notexists