Pesquisar este blog

quarta-feira, 24 de novembro de 2010

Interpretando código SQL de forma eficiente (segmentada)

imagePara este artigo, estou utilizando o Microsoft SQL Server 2008, porém se aplica a qualquer gerenciador de banco de dados.

Em muitos treinamentos que prestei, ou até mesmo acompanhando outros profissionais que ainda estão em estágio de aprendizado, percebo uma enorme dificuldade em conseguir enxergar realmente o que são todas aquelas pernas dentro de um único select. É left join pra cá, distinct pra lá, group em cima, e order em baixo. Existem select’s que chegam a ultrapassar páginas de código, para uma única consulta. E isso é muito comum, pois uma programação limpa no SQL consiste em não utilizar cursores, loops, tabelas temporárias, usando somente em casos muito específicos. O ideal é reduzir o custo das rotinas, reduzindo o número de operações no banco de dados.

O exemplo que vamos estudar nesta publicação é um trecho de uma Stored Procedure responsável por gerar o faturamento a partir de uma ordem de serviço (ADOOS). Este faturamento gera nota fiscal, títulos a receber, entre outras informações. De forma a minimizar o custo total da query, uni em um único select todos os dados necessários para executar este faturamento. Esta união resultou em um select que busca ao mesmo tempo, dados de 12 diferentes tabelas. O que vamos entender, é como fazer a interpretação de uma query extensa, utilizando a técnica de segmentação do código.

Vamos dar uma olhada no trecho do código:

image

Esta é uma query de nível fácil a intermediário, pois todas as tabelas possuem relacionamento um para um. Veja que utilizei apelidos para as tabelas (cadastro – e, cidade – f, cidade – g), repeti as tabelas CADASTRO e CIDADE pois preciso dos dados de cadastro e estado tanto do cliente quanto da empresa.

 

Se para você, esta query é assustadora, então você está no post certo!

 

Em primeiro lugar, e não sei por qual razão, a maioria dos programadores iniciantes NÃO LÊEM. É isso mesmo, não lêem o que está escrito na tela. Uma query exige uma leitura muito mais minuciosa que um texto, pois o SQL tem que ser exato, todos os laços devem ser fechados para que a query rode corretamente. É matemática, teoria dos conjuntos.

O primeiro passo, é identificar cada tabela, os dados que serão extraídos dela e qual o seu relacionamento com as demais.

image

ADOOS – Quando esta rotina é chamada, recebe como parâmetro o número da ordem de serviço. A tabela ADOOS é onde ficam armazenadas todas as ordens de serviço, contendo data de abertura, cliente, tipo de ordem de serviço, etc. A chave primária desta tabela é EMPRESA, SÉRIE E NR_OS.

ADOOSOutra – Tabela auxiliar à tabela principal, traz informações adicionais como programação de entrega, plano gerencial, centro de custo, etc. O seu relacionamento é de 1x1 (um registro em ADOOS para um registro em ADOOSOutra). Mesma chave primária que ADOOS.

ADOOSEncerra – Assim como no exemplo acima, esta tabela também é 1x1, tendo a mesma chave primária que a ADOOS.

Cadastro (d) – contém os dados de cadastro do cliente, pois na tabela ADOOS somente é especificado o código.

Cadastro (e) – contém os dados da EMPRESA que emitiu a ordem de serviço, a tabela ADOOS se relaciona com esta tabela através da chave EMPRESA.

Cidade (f) – Tabela que será relacionada à tabela Cadastro (d), para buscar o código do estado (UF) do cliente.

Cidade (g) – Tabela que será relacionada à tabela Cadastro (e), para buscar o código do estado (UF) da empresa.

Condicaovenda (h) – Tabela que contém informações inerentes à condição de venda estabelecida na tabela ADOOS (coluna cd_condicaovenda).

As demais tabelas não precisamos colocar neste exemplo, já temos o suficiente. Bom, já identificamos o papel de cada tabela. Este trabalho pode ser realizado lendo a estrutura de cada tabela, fazendo consultas, consultar a estrutura no modo design, e assim por diante. Até aqui não tem segredo, certo?

Depois que nós concluímos este levantamento, vamos então analisar todas as referencias na parte WHERE, onde estabelecemos os relacionamentos entre as tabelas:

ADOOS ~> É a tabela que nos serve de parametro, pois temos o número da ordem de serviço. É ela que receberá a comparação com os parâmetros recebidos pelo procedimento:

image

ADOOSOutra ~> Se relaciona com a tabela ADOOS através das chaves primárias. Já identificamos seu relacionamento.

image

ADOOSEncerra ~> mesmo caso da ADOOSOutra, relacionamento 1x1 através das chaves primárias.

image

Tabelas de cadastro e respectivas cidades ~> veja que o código de cadastro da tabela A (ADOOS) é igual ao código de cadastro da tabela D (CADASTRO DO CLIENTE). O código da cidade F é igual ao código da cidade da tabela CADASTRO DO CLIENTE D. Também relacionamos o código da empresa que emitiu a OS com a tabela CADASTRO E, que também relaciona o seu respectivo código de cidade com a tabela CIDADE G.

image

Leia atentamente o código. Nunca observe a query como um todo, leia de forma segmentada. Primeiro veja as tabelas, se concentre em entender qual o mapeamento de dados responsável por cada uma. Depois, identifique cada relacionamento entre as tabelas. Veja item por item, para identificar possíveis erros de JOIN (relacionamento). Mas é necessário que seja observado item por item. Importante lembrar para que sempre leia atentamente as mensagens de erro durante execuções no sql. Muitas vezes, ao executar um procedimento, o usuário vê a mensagem vermelha de erro, e imediatamente coloca na cabeça: deu erro, vou procurar… mas nunca lê a mensagem, que diz exatamente onde está o problema! Digo isso por que tive esta experiência com uma pessoa que está aprendendo nesta semana *-*

\o/

Nenhum comentário:

Postar um comentário