Trabalhando com Bancos de Dados no VB

Nota: Nas primeiras seções que se seguem serão expostas algumas idéias básicas sobre bancos de dados. Se você já tem um conhecimento introdutório sobre o tema, poderá saltar algumas dessas seções.

Um sistema de banco de dados é simplesmente um sistema de manutenção de arquivos e informações relacionadas. Imagine um banco de dados como um grande armário para o arquivamento de informações. Dentro das gavetas - os arquivos - guardamos de maneira ordenada as informações necessárias para o exercício de alguma atividade. Se contratarmos um escriturário para manter o arquivo teremos o equivalente a um sistema gerenciador de banco de dados. Em outras palavras, um banco de dados pode ser considerado um conjunto de arquivos de dados, capaz de oferecer diversos recursos automáticos ao usuário de modo que diversas operações podem ser realizadas, a saber:

A adição e remoção de arquivos do banco de dados;

A inserção e remoção de dados dos arquivos existentes;

A recuperação e a atualização de dados nos arquivos existentes.

Fica claro, portanto, que um sistema de banco de dados compõe-se , basicamente, de dois subsistemas. O primeiro deles envolve simplesmente o armazenamento físico dos dados. O segundo envolve um subsistema capaz de manter e recuperar as informações armazenadas. Este seria, na analogia do armário, o escriturário responsável pela manutenção do arquivo. Ambos os subsistemas são cruciais para a realização da tarefa. Suponha que o mecanismo de organização dos dados no arquivo físico fosse grosseiramente projetado. Certamente o trabalho do arquivista seria um fracasso.

Sistemas de Banco de Dados

Os sistemas de bancos de dados mantêm informações significativas para pessoas ou empresas - informações necessárias para o processo de tomada de decisões para estas mesmas pessoas ou empresas. Um sistema de banco de dados tem por finalidade manter informações e disponibilizá-las quando solicitadas.

Para maior eficiência em uma organização, os sistemas de bancos de dados costumam apresentar duas características básicas, representando sua maior vantagem:

Integração. O banco de dados pode ser imaginado como a unificação de diversos depósitos de dados de outra forma distintos, eliminando total ou parcialmente qualquer redundância. Uma conseqüência da integração do banco de dados é que, em geral, um usuário só estará interessado em um subconjunto dos dados, fazendo com que cada usuário perceba o banco de dados de maneira distinta de todos os demais.

Compartilhamento. Parcelas isoladas de dados podem ser compartilhadas por diversos usuários de um banco de dados. Todos os usuários podem ter acesso á mesma parcela de dados, usando-a com finalidades diversas. Diferentes usuários podem ter acesso às mesmas parcelas de dados ( acesso concorrente ).

Tais características de um banco de dados corporativo permitem à organização o controle centralizado de suas informações operacionais e gerenciais. Isto pode ser decisivo para a organização facilitando e agilizando a tomada de decisões.

Sistema Gerenciador de Banco de Dados

Entre o armazenamento físico dos dados no banco de dados e os usuários e aplicações do sistema encontra-se o sistema gerenciador de banco de dados ( Database Management System - DBMS). Todas as solicitações de acesso ao banco de dados, sejam elas dos usuários diretos ou dos aplicativos, são manipuladas pelo DBMS, isolando os usuários dos detalhes de armazenamento a nível de hardware.

Os Usuários

Na ponta final do processo encontram-se os usuários. Não apenas os beneficiários das informações mantidas pelo sistema. Todos aqueles que, de uma forma ou de outra, são obrigados a se relacionar com o banco de dados (físico) através do DBMS são usuários do sistema, a saber:

O programador, responsável pelos aplicativos que utilizam o banco de dados.

O usuário final, que interage com o sistema a partir dos aplicativos.

O administrador do banco de dados, a quem cabe organizar, padronizar e manter o acesso aos dados da empresa.

Os Dados

Independente de quaisquer outras considerações, um banco de dados não passa de uma coleção de dados operacionais - informações importantes para organizações e indivíduos. Por mais avançado e eficiente que seja o DBMS, se os dados não forem armazenados com uma estruturação lógica clara e consistente, todo este aparato será em vão.

Considere o caso mais simples de um caderno de telefones. Eu desejo anotar o telefone da empresa Couves & Repolhos Ltda., especializada em atendimento médico de emergência. Assim, anoto o telefone na letra C, usando o critério do nome da empresa. Numa emergência, quando a informação é extremamente necessária, é bem possível que eu esqueça o nome da empresa. Como o telefone não foi anotado também nas letras E - emergência - e M - médicos, a recuperação da informação será penosa. A organização do banco de dados foi ineficaz. Se, num caso simples como este a organização lógica do armazenamento da informação é crítica, imagine o problema - bem mais complexo - de projetar um banco de dados para atender às necessidades de uma grande empresa. E o melhor DBMS do mundo não pode resolver este problema.

Consideremos agora a natureza do dado armazenado no banco de dados. De maneira nenhuma, no exemplo anterior, eu pensaria em anotar na minha caderneta de telefones, o nome de todos os médicos e paramédicos da empresa Couves & Repolhos Ltda. Essa informação, do meu ponto de vista, é transitória, não é essencial à minha tomada de decisão.

Assim, há duas classes de informações que não deverão compor a organização lógica do meu banco de dados, ainda que circulem em torno do sistema como um todo:

Os dados temporários. Aquelas informações que entram no sistema, mas são transitórias. Ainda que provoquem alterações nos dados operacionais, tais informações não devem fazer parte do banco de dados. Um exemplo bem simples é um dado calculado. De forma alguma ele deve ser armazenado. Quando for necessário, calcule-o a partir dos dados permanentes.

Os dados de saída - mensagens e resultados procedentes do sistema. Ainda que derivadas dos dados operacionais, tais informações não fazem parte do banco de dados em si.

Ainda que as qualidades de um DBMS não garantam uma organização eficaz dos dados - esta é uma tarefa dos projetistas do sistema específico - a natureza desta organização dependerá das características do sistema gerenciador, sendo limitada por elas.

Isto porque o DBMS age como um intermediário entre o aplicativo e os dados. Sendo assim, a maneira como o sistema admite a organização dos dados influirá criticamente no resultado final. O DBMS manipula todos os acessos ao banco de dados. Quando o usuário emite uma solicitação de acesso, usando, por exemplo SQL ou um aplicativo de front-end específico, o DBMS:

Intercepta a solicitação e analisa-a;

Determina as permissões de acesso do usuário e define a estrutura de armazenamento;

Executa as operações necessárias no banco de dados armazenado.

Os diversos esquemas de armazenamento e recuperação da informação serão, portanto, decisivos para o projeto de estruturação do banco de dados.

A Organização dos Dados em Tabelas

O termo tabela faz parte do cotidiano de quem lida com banco de dados. Agrupar informações em tabelas é a forma comum de se organizar dados na maioria dos sistemas de armazenamento. Antes, porém, que a informação seja agrupada em tabelas é preciso submete-la a um agrupamento de nível mais básico: o registro. Um registro é um conjunto de informações que descrevem alguma coisa de modo satisfatório para algum propósito. Suponhamos que você queira anotar o endereço de alguém numa agenda. Inicialmente você anota o nome da pessoa, depois a rua, o número, bairro, cidade. Se para o seu propósito de localização futura da pessoa estes dados bastam, você acaba de criar um registro desta pessoa na sua agenda. Caso você não tenha uma agenda, mas queira organizar suas informações de endereços numa folha de papel, uma alternativa é criar uma tabela, onde cada coluna será usada para relacionar uma das partes do endereço a ser anotado. Você terá então uma coluna para o nome da pessoa, outra para a rua, outra para o número e assim por diante. Cada novo endereço será escrito na primeira linha vaga da tabela após os últimos dados que já foram adicionados. Você pode dar um nome para a sua tabela, por exemplo, endereços de clientes. Se fizer também uma tabela para endereços de amigos, poderá dar a ela outro nome. Cada coluna da tabela também pode receber um nome que clarifique qual parte do endereço está escrita nela. No caso de endereços pode ficar fácil compreender qual coluna corresponde ao nome, qual à rua, mas nada garante que alguém não irá confundir bairro com cidade se não for posto um título em cada coluna para deixar as coisas mais claras. Se o indivíduo que for examinar a sua tabela for um computador então, não tenha dúvidas de que ele precisará de tudo muito claro. Se esta tabela vier a ser parte de um banco de dados computadorizado, cada linha da tabela será um registro e cada coluna um campo de registro. Com o computador sabendo identificar cada coluna da tabela por um nome de campo, poderemos pedir a ele que nos apresente os registros ora ordenados por nome, ora por endereço ou por qualquer outro campo que faça parte do registro da tabela. A este conjunto de campos e à posição relativa que ocupam dentro do registro chamamos de LayOut do registro.

Sistemas Relacionais

Nos últimos anos, o modelo relacional tem se tornado um padrão para o projeto de bancos de dados. Isto se dá em razão do poder do modelo relacional em si e também porque ele oferece uma linguagem padrão de comunicação chamada SQL (Structured Query Language) que permite a muitas ferramentas e produtos de banco de dados trabalharem juntos de uma maneira consistente e compreensível. Num sistema relacional:

Os dados são percebidos pelos usuários como tabelas;

As operações à disposição do usuário (por exemplo, de recuperação dos dados) geram novas tabelas a partir das antigas.

O usuário de um sistema não-relacional, ao contrário, vê outras estruturas de dados e necessita de operações diferentes para manipulá-los. Por exemplo, o IMS, um sistema hierárquico, apresenta os dados sob a forma de um conjunto de estruturas de árvore. As operações para manipular tais estruturas incluem, por exemplo, mecanismos para percorrer caminhos para cima e para baixo nos galhos da árvore.

RDBMS Mono-usuários Tradicionais

Nota: RDBMS é abreviatura de Relational DataBase Management System.

Gerenciadores tradicionais de bancos de dados relacionais, como o dBase e o Paradox, utilizam arquivos separados para cada tabela, índice ou coleção de índices disponível no sistema. Neles as tabelas usam registros de comprimento fixo. Por exemplo, num campo caractere, a especificação do tamanho máximo de cada campo é feita de tal forma que valores inferiores ao máximo são automaticamente preenchidos com espaços em branco. Os RDBMS Btrieve, por exemplo, admitem armazenamento de campos caractere de tamanho variável, promovendo uma importante economia de espaço.

Porém, a manipulação dos dados nas tabelas e a manipulação dos índices nestes tipos de RDBMS é responsabilidade da aplicação. Esta traduz comandos de alto nível, como o comando SQLSELECT ou o comando dBase LIST, em instruções de baixo nível. São estas as instruções que manipulam diretamente os registros das tabelas.

RDBMS Cliente-Servidor

Os sistemas cliente-servidor diferem grandemente dos sistemas mono-usuários.

A primeira distinção é que o comando SQL emitido pela aplicação de front-end é executado pelo servidor (back-end). Quando a estação envia um comando SELECT para o servidor, somente os registros correspondentes às especificações da consulta são retornados à estação. O servidor é responsável pela execução dos comandos enviados pelas estações, controlando os acessos concorrentes ao banco de dados e a consistência das entradas.

Bancos de Dados Locais e Remotos

Antes de situarmos o dispositivo de banco de dados do VB ( o Microsoft Jet Database Engine) na família de bancos de dados relacionais, é conveniente fazermos mais algumas distinções. Um sistema de banco de dados, como já sabemos, possui três componentes: os dados armazenados, o sistema gerenciador e o aplicativo de front-end. Do ponto de vista físico, tais componentes podem se localizar todos na mesma máquina, configurando um sistema mono-usuário. Podem, contudo, localizar-se em diferentes computadores ligados por uma rede. Por exemplo, os dados armazenados podem residir num servidor de arquivos central e a interface com o usuário (o aplicativo) em diferentes estações de trabalho, permitindo acesso concorrente de diversos usuários aos mesmos dados.

Cliente-Servidor vs. Remoto

Uma importante distinção nas aplicações de bancos de dados projetados para ambientes de rede consiste na diferença entre banco de dados remoto e banco de dados cliente-servidor. Num sistema cliente-servidor, o dispositivo gerenciador de banco de dados está localizado no servidor central, ao lado dos dados armazenados. O mesmo dispositivo gerenciador apode servir a muitas aplicações clientes ao mesmo tempo, manipulando os dados armazenados e retornando os registros solicitados para cada aplicação local. Num sistema remoto, o dispositivo gerenciador de banco de dados se localiza no mesmo computador onde reside a aplicação do usuário; apenas os dados residem num computador remoto.

O Microsoft Jet - um RDBMS Não-Tradicional

O gerenciador de banco de dados do VB, o Microsoft Jet - Inteiramente compatível com o Microsoft Access - não é um sistema cliente servidor. Ele é um dispositivo de acesso a banco de dados residente em DLLs ligadas ao programa em tempo de execução. Havendo diversas cópias da aplicação em diversas estações, cada uma delas terá sua cópia local do dispositivo Jet, ainda que acessem a mesma base de dados remota. Esta distinção não tem alcance meramente teórico. Ao contrário, esta característica afeta a performance global do sistema. Num sistema cliente-servidor, trafegam pela rede, grosso modo, apenas aos comandos de consulta e atualização e os subconjuntos de dados eventualmente solicitados. Numa arquitetura como a do Jet - como dados e gerenciador localizam-se em máquinas diferentes - muito mais informações trafegarão pela rede.

É possível, contudo, criar aplicações cliente-servidor em VB, conectando-as a uma fonte de dados com suporte à ODBC ( Open Database Connectivity), tal como o Microsoft SQL Server. Nestes casos, as consultas são passadas diretamente ao dispositivo servidor ou utilizam procedimentos remotos nele armazenados.

Ainda que não seja um gerenciador cliente-servidor, o Microsoft Jet pertence a uma categoria diferente dos RDBMS tradicionais, porque tem pouca semelhança com sistemas como o dBase e o Paradox. O dispositivo RDBMS incorporado ao VB possui muitas características em comum com os bancos de dados cliente-servidor, em particular com o Microsoft SQL Server. Tais características comuns são:

Todas as tabelas e índices do banco de dados são armazenados num único arquivo com a extensão .MDB.

Os campos de data suportam informação de hora.

Os campos suportam valores nulos (Null).

Admite o armazenamento permanente de comandos SQL.

O tamanho dos campos OLE Object (LongBinary) é limitado apenas pelo espaço em disco e não pela estrutura do arquivo.

É possível forçar a integridade referencial entre as tabelas e a integridade de domínio - entre os campos - da tabela.

Inclui capacidades de manutenção de segurança de acesso.

Inclui, automaticamente ou por programa, capacidade para gerenciar o acesso concorrente.

Tais características tornam o Microsoft Jet - e o Microsoft Access - ideais para aplicações de banco de dados robustas, mas de características intermediárias entre os grande sistemas cliente-servidor e os pequenos sistemas mono-usuários. Como linguagem de programação, porém, o VB não sofre essa restrição, permitindo a conexão com sistemas cliente-servidor via tecnologia ODBC. Neste caso, a interface de programação poderá ter que se adaptar às características do RDBMS específico.

Conceitos Básicos dos Bancos de Dados Relacionais

Já falamos um pouco sobre alguns desses conceitos - tabelas, registros e campos - mas aqui vamos procurar relacioná-los a outros ainda não citados. Ainda sobre tabelas devemos lembrar que:

É desejável, mas não essencial, que cada registro dentro de uma tabela tenha um conjunto de campos cuja combinação de valores seja capaz de individualizar inequivocamente o registro dentro da tabela. Esse conjunto é chamado identificador e é boa prática de projeto de banco de dados a sua existência.

Um campo que possua a capacidade de ser um identificador é chamado de chave primária. Por definição, um conjunto de valores dos campos constituintes da chave primária deve ser único para cada registro. Registros em tabelas relacionadas podem ter valores idênticos aos da chave primária de uma das tabelas. O valor idêntico ao da chave primária é conhecido como chave externa.

A tabela abaixo resume os principais termos utilizados no projeto e implementação de sistemas de bancos de dados relacionais.

Figura 13.1

Modelagem de Dados

É o momento de fundamentarmos toda a teoria discutida ao longo deste capítulo com orientações precisas sobre o problema principal - e, portanto, o primeiro a ser enfrentado - no desenvolvimento de um sistema de banco de dados: como projetar a base de dados da aplicação? A melhor maneira de tratarmos do assunto é, certamente, com a ajuda de um exemplo concreto de modelagem de dados.

Exemplo de Projeto de um Banco de Dados

Vamos supor que você foi contratado por uma firma distribuidora de material de limpeza para desenvolver um sistema de controle da atividade. Naturalmente, seu cliente não sabe com exatidão o que quer. Como sempre, ele sabe apenas que precisa automatizar o negócio, de modo a favorecer o aumento de produtividade e a expansão das suas atividades. O sistema atual - um controle desordenado através de fichas de papelão - atingiu o seu limite. Mantê-lo significa contratar novos empregados e ver boa parte das receitas se escoando em prejuízos causados pelo descontrole. Sua tarefa é, portanto, evitar o caos.

Como este não é um manual sobre análise de sistemas, passaremos por alto pelos passos necessários para alcançar a fase que nos interessa. Diremos apenas que, após algum esforço, você chegou a algumas conclusões sobre o funcionamento do negócio da empresa, a saber:

A firma - Limpa Tudo Materiais de Limpeza Ltda. - obtém seus produtos de um conjunto de empresas fornecedoras. Estas podem ou não ser os fabricantes originais. Cada uma delas fornece um ou mais itens para o estoque, acontecendo algumas vezes que duas diferentes empresas forneçam o mesmo produto. A decisão sobre de qual comprar é feita com base numa série de critérios gerenciais fora do domínio do sistema a ser desenvolvido.

O pedido de novos itens é feito através de contatos telefônicos com cada fornecedor. Geralmente, cada empresa possui um ou mais empregados encarregados de atender aos pedidos do seu cliente. Tais pedidos são feitos sempre que o estoque de um item baixa até uma quantidade considerada mínima pela firma.

A baixa do item do estoque é feita pelo funcionário do almoxarifado sempre que é levado pelo pessoal da entrega e não quando é feito o pedido. Isto faz com que alguns pedidos não possam ser atendidos antes de um novo fornecimento.

Os clientes da Limpa Tudo - também empresas - solicitam periodicamente quantidades variáveis de cada item, pelo telefone.

Para atender a seus muitos clientes, a Limpa Tudo mantém um grupo de vendedores. Estes recebem uma comissão de 5% por cada venda efetuada.

A equipe de entrega recebe um roteiro prévio, contendo as diversas faturas, onde são relacionados os itens entregues e o preço dos produtos.

Naturalmente, esse levantamento é insuficiente para o desenvolvimento de um sistema real, mas deve bastar para o nosso exemplo de modelagem de dados. Assim, com algum esforço, você chegou aos requisitos básicos do aplicativo. O sistema deve cumprir, no mínimo, as seguintes tarefas:

Controlar os itens em estoque. O sistema deve efetuar uma baixa "virtual" do produto quando o pedido é feito e uma baixa "real" quando é entregue. Deste modo, o pessoal da Limpa Tudo saberá exatamente quando solicitar um novo fornecimento, sem precisar manter estoques exagerados e sem deixar de atender nenhum cliente com prontidão.

Faturar os pedidos aos fornecedores, quando um item em estoque estiver abaixo de um limite crítico.

Faturar os pedidos dos clientes, baixando, no ato da solicitação, o item do estoque.

Controlar as vendas de cada empregado, visando o cálculo das comissões.

Manter um cadastro de clientes.

Manter um cadastro de fornecedores.

Oferecer um catálogo de produtos aos clientes.

Fornecer uma lista de itens para entrega, bem como faturas e os diversos relatórios necessários ao controle total do negócio.

Os Diversos Documentos de Entrada

O próximo passo será analisar os diversos documentos e controles mantidos pela Limpa Tudo. Tais documentos servirão de ponto de partida para a criação das múltiplas tabelas gerenciadas pelo sistema. Vejamos cada caso.

O primeiro documento relevante será o utilizado no almoxarifado, para o controle de produtos em estoque. A Limpa Tudo mantém atualmente um fichário de cartolina com as seguintes informações:

Nome e descrição do produto.

Data da entrada de novos itens no estoque.

Quantidade de itens acrescentados nesta data.

Data de saída de alguns itens do estoque.

Quantidade de itens baixados nesta data.

Quantidade total de itens atualmente em estoque.

Quantidade mínima de itens a serem mantidos em estoque.

Nome e CGC das empresas fornecedoras do produto.

Endereço de cada empresa fornecedora.

Telefone de cada empresa fornecedora e nome dos diversos vendedores responsáveis pelo contato com a Limpa Tudo.

Preço corrente do produto cobrado por cada uma das empresas fornecedoras.

O almoxarifado da Limpa Tudo é razoavelmente organizado. Como o empregado deste setor é o responsável pelos pedidos de fornecimento, ele mantém controle sobre cada pedido de fornecimento efetuado, visando cobrar eventuais demoras e auxiliar o patrão no planejamento do fornecimento. Este controle é feito num livro comum, onde cada folha registra as informações a seguir, descartadas sempre no atendimento do pedido pelo fornecedor:

CGC e Razão Social do fornecedor.

Endereço e telefones para contato do fornecedor.

Nomes dos diversos contatos na empresa.

Nome e quantidade do item solicitado.

Data do pedido e data prevista para a entrega.

O almoxarifado mantém ainda um catálogo completo de todos os fornecedores, também num fichário de cartolina. É este o documento consultado para montar o controle de pedidos de fornecimento e possui as seguintes informações:

Nome e CGC da empresa fornecedora.

Endereço completo do fornecedor, contendo rua e número, CEP, cidade e estado.

Os diversos telefones utilizados para contatar a empresa.

O nome de cada um dos contatos no fornecedor.

Uma lista com o nome, a descrição e o preço de cada um dos produtos fornecidos.

A equipe de vendas, como não poderia deixar de ser, mantém também um conjunto de documentos visando controlar sua atividade e (sobretudo!) as comissões devidas a cada um. O primeiro documento referido será o mantido para cada venda efetuada. Este contém as seguintes informações:

Nome e CGC da empresa cliente.

Endereço completo do cliente.

Nome de cada um dos itens vendidos.

Quantidade e preço unitário de cada um dos itens vendidos.

Preço total de cada conjunto de produtos.

Valor total da fatura.

Data da venda.

Nome do vendedor e valor da comissão pela venda.

Este documento é emitido em diversas vias, destinadas ao almoxarifado, para providenciar a entrega, à contabilidade, etc. Uma das cópias fica em poder do vendedor e é o seu controle de comissões, apresentado periodicamente ao patrão, para recebimento dos valores devidos.

Obviamente, a equipe de vendas mantém um cadastro completo de todos os clientes, mesmo os eventuais. Este cadastro, sob a forma do velho fichário de cartolina, serve não apenas como fonte de consulta mas também como fonte de dados para marketing ativo. O fichário possui as seguintes informações:

Razão social e CGC da empresa cliente.

Endereço completo do cliente.

Os diversos telefones para contato com o cliente, bem como o nome dos empregados responsáveis.

Uma lista contendo o nome e a descrição dos itens habitualmente adquiridos pelo cliente.

A equipe de vendas mantém um catálogo completo de todos os itens disponíveis, contendo as seguintes informações:

Nome de cada item.

Descrição do item.

Preço de venda do item.

O último documento de interesse é o relatório utilizado pelo pessoal da entrega no ato do despacho para os diversos clientes. As seguintes informações são relevantes para a Limpa Tudo:

CGC e nome da empresa cliente.

Endereço para entrega dos produtos.

Nome do item entregue.

Quantidade entregue.

Preço total.

Transformação em Tópicos

O primeiro passo na criação das tabelas é definir o tópico de cada uma. Em outras palavras, precisamos definir a entidade do negócio representada pela tabela. Como ficou evidente na seção anterior, a Limpa Tudo é uma empresa bastante organizada. Sendo assim, podemos utilizar os próprios documentos de entrada nessa definição.

Neste primeiro momento, definiremos apenas o tópico de cada tabela e as informações relacionadas a ele, sem quaisquer preocupações quanto à redundância dos dados. Este passo é fundamental, já que uma tabela é um conjunto de informações referentes a um tópico determinado. Além disso, já daremos nomes definitivos para cada item de dados, de acordo com as convenções permitidas pelo Microsoft Jet.

Evidentemente, a entidade-chave no sistema será o Produto vendido pela Limpa Tudo. A Figura 13.2 descreve, sumariamente, o tópico Produtos. Os campos com asterisco representam aquelas informações passíveis de repetição dentro do tópico:

Figura 13.2: O tópico Produtos.

O segundo tópico a ser descrito é o de Fornecedores, listado na Figura 13.3:

Figura 13.3: O tópico Fornecedores.

O próximo tópico abordado - os Clientes - fecha o conjunto de entidades básicas representadas. Veja a Figura 13.4:

Figura 13.4: O tópico Clientes.

Note que não incluímos na tabela um campo para armazenar os itens habitualmente adquiridos pelo cliente, mantido pelos documentos da Limpa Tudo. Não o fizemos porque essa informação tem finalidade estatística e pode ser facilmente obtida da tabela de pedidos, vista mais adiante. Isso sugere uma importante recomendação: não armazene informações calculadas ou que possam ser obtidas por outros meios, ainda que indiretos. Tais informações não são essenciais. A única razão para armazená-las decorre de considerações de performance. Contudo, nestes casos, deve-se avaliar cuidadosamente os ganhos obtidos.

O próximo tópico descrito será o Estoque. Aqui será importante distinguir a posição corrente dos itens em estoque do fluxo de entrada e saída dos produtos. Este será mantido em separado, já que representa um tópico diverso, com finalidade diversa - um histórico de operações. A Figura 13.5 lista, então, o tópico:

Figura 13.5: O tópico Estoque.

Abordaremos agora o fluxo diário de itens em estoque. A Figura 13.6 lista a definição do tópico Transações:

Figura 13.6: O tópico Transações.

Como se pode notar, não incluímos as informações referentes ao fornecedor e ao preço do produto, mantidas no documento da Limpa Tudo, visto na seção anterior. Tais informações não se referem ao assunto representado pelo tópico presente.

Tratemos agora do pedido de Fornecimento, tópico listado na Figura 13.7:

Figura 13.7: O tópico Fornecimento.

A Figura 13.8 lista o próximo tópico relevante - o pedido de Vendas:

Figura 13.8: O tópico Vendas.

Normalização

Ao longo da seção anterior, preocupamo-nos somente em definir cada assunto ou tópico e as informações necessárias para descrevê-lo por completo. Em momento algum analisamos o problema da organização eficiente de cada um. Há grupos de informações repetidas dentro de um mesmo tópico; há também informações repetidas desnecessariamente entre tópicos. Devemos eliminar esta redundância.

Um outro problema é que as entidades básicas estão definidas por seus nomes. Isto pode ocasionar inconsistência dos dados, já que nomes longos podem ser informados, favorecendo erros de digitação e dificultando a localização. É comum a utilização de códigos numéricos para essas entidades.

Um outro problema no qual podemos avançar é definir claramente o tipo de dado requerido por cada um dos campos, para garantirmos rigorosa consistência entre eles desde já. Campos conceitualmente afins devem receber, além de um mesmo nome, tipos de dados rigorosamente iguais.

Logo no tópico Produtos encontramos matéria para discussão. Ele possui duas informações passíveis de repetição dentro da tabela - Nome do Fornecedor e Preço de Compra - ambas relacionadas. Esta redundância deve ser eliminada. Não admita grupos de informações repetidas dentro de uma tabela. Neste caso, divida as informações em duas tabelas.

Uma outra questão diz respeito à Categoria do produto. Este campo possui, por definição, um conjunto definido de valores possíveis, conhecidos de antemão. Assim, é conveniente codificarmos o campo, colocando sua descrição em outra tabela. Embora a economia de bytes seja pequena, o princípio é útil. Encontrando valores de um campo selecionáveis de um conjunto limitado de valores possíveis, é conveniente situá-los numa tabela em separado -conhecida como tabela de autoconsulta.

Assim, o tópico Produtos pode ser organizado em três tabelas separadas,

listada na Figura 13.9:

Figura 13.9: O tópico Produtos dividido em tabelas.

O tópico fornecedores também padece de alta redundância. Os campos Nome do Produto e Preço de Compra, relacionados a um Fornecedor, já estão definidos na tabela Produtos Por Fornecedor. Podem, portanto, ser eliminados. Cidade e UF podem compor uma tabela em separado pela mesma razão usada para criar a tabela Categorias. Apenas o CEP basta para definir uma cidade e um estado.

Note também que as informações sobre o Telefone e o Contato, parte integrante do tópico Fornecedores, podem se repetir. Como já vimos, nestes casos devemos criar uma outra tabela. Esta, entretanto, será conceitualmente distinta, por exemplo, da tabela Categorias ou da tabela de Localidades.

Em primeiro lugar, cada registro na tabela Fornecedores poderá se referir a inúmeros registros na tabela de Telefones. Além disso, não faz sentido mantermos um registro na tabela de Telefones sem um correspondente na tabela de Fornecedores. Neste caso, devemos criar o que se convencionou chamar uma tabela-filha. Esta é uma tabela na qual todas as entradas compartilham algumas informações comuns, armazenadas em outra tabela. No momento, isso não terá efeitos práticos. A razão dessa consideração ficará clara na próxima seção.

Vale, porém, uma observação. Sempre que criar uma tabela-filha, assegure-se de que as atualizações efetuadas na tabela-pai se propaguem para a filha. Além disso, não admita registros órfãos (sem correspondência na tabela-pai) na tabela-filha.

Desse modo, podemos criar as tabelas definidas a seguir para melhor representar o tópico Fornecedores:

Figura 13.10: O tópico Fornecedores dividido em tabelas.

O tópico Clientes não apresenta nada de novo. Os campos Cidade e UF já estão definidos na tabela Localidades e podem ser eliminados. Os campos Telefone e Contato devem receber o mesmo tratamento da tabela Telefones dos Fornecedores, criando-se uma tabela-filha. Assim, precisamos criar somente as tabelas descritas a seguir:

Figura 13.11: O tópico Clientes tratado.

O tópico Estoque também pode ser reduzido. Os campos Nome do Produto, Descrição e Categoria podem ser substituídos pelo código do Produto, tal como definido na tabela Produtos. Assim, a tabela Estoque pode reduzir-se às definições listadas na Figura 13.12:

Figura 13.12: A tabela Estoque.

Nos tópicos Transações e Fornecimentos basta substituir os campos Nome do Produto e Razão Social pelos seus respectivos códigos. Os tópicos podem ser, então, definidos como na Figura 13.13:

Figura 13.13: As tabelas Transações e Fornecimento.

O tópico Vendas requer algumas considerações. O campo Preço de Venda é redundante, já que foi definido na tabela Produtos. Os campos referentes ao produto e à quantidade vendida podem repetir-se, já que uma mesma venda pode abranger inúmeros itens. A solução é, portanto, criar uma tabela-filha. Para referirmos as informações repetidas podemos criar um número identificador único, normalmente utilizado para fins de controle fiscal.

Um outro aspecto refere-se ao nome do vendedor. Do mesmo modo que o campo Categoria do produto, podemos criar uma tabela de autoconsulta de Vendedores e atribuir um código inequívoco a cada um deles. Outra questão refere-se às comissões. Em princípio, a comissão é única e calculada a partir do valor total da venda. Pode ser possível, entretanto, a utilização de comissões crescentes por faixas de valores, visando estimular o negócio. Justifica-se, assim, uma tabela específica.

O tópico, então, pode ser definido como descrito na Figura 13.14:

Figura 13.14: O tópico Vendas normalizado.

Relacionamento Entre Tabelas

O passo seguinte é definir os diversos relacionamentos entre as tabelas. Como já vimos, o relacionamento se define a partir da duplicação de atributos de diferentes tabelas: a chave primaria na tabela primária e a chave externa na tabela dependente. Cabe, portanto, definirmos a chave primária de cada tabela a ser relacionada às demais. Como já sabemos, a chave primária individualiza um registro, não podendo, portanto, conter valores repetidos em mais de um registro da tabela.

A Figura 13.15 lista os campos sugeridos como chave primária da base de dados que viemos modelando:

Figura 13.15: As chaves primárias de campo único do base de dados da Limpa Tudo.

Evidentemente, não pudemos definir uma chave primária de campo único para aquelas tabelas que representam os históricos das operações da Limpa Tudo. Nessas tabelas, um único campo não pode identificar um registro. O mesmo não pode ser dito, porém, da combinação de alguns campos de cada tabela. Por exemplo, na tabela Faturas, a combinação de um código de Fatura e de um código de Produto identifica univocamente o registro. A Figura 13.16 lista as demais chaves primarias do banco de dados:

Figura 13.16: As chaves primárias de mais de um campo da base de dados da Limpa Tudo.

Por que essa preocupação em garantir que todas as tabelas possuam chaves primárias? No Microsoft Jet, só é possível estabelecer relacionamentos entre tabelas a partir de campos definidos como chaves primárias. Em essência, um relacionamento exprime uma ligação entre a chave primária de uma tabela e a chave externa de uma tabela dependente.

Estamos prontos, agora, para definir os relacionamentos entre as diversas tabelas. Comecemos pelo tópico Produtos. Você se lembra que dividimos o tópico em três tabelas relacionadas - Produtos, Categorias e Produtos Por Fornecedor. Trata-se, pois, de definir claramente como elas se relacionam.

Um registro na tabela Categorias pode referenciar vários registros na tabela Produtos. E mais: havendo necessidade de se alterar uma determinada codificação de categoria de produto, essa atualização deve-se propagar para a tabela dependente; é o caso de se impor a integridade referencial no relacionamento, forçando a propagação de eventuais atualizações.

Por outro lado, um registro na tabela de Produtos pode referenciar vários registros na tabela Produtos Por Fornecedor, na medida em que um mesmo item pode ser fornecido por diferentes empresas. Aqui também deve-se impor integridade referencial entre as tabelas: removendo-se um registro na tabela de Produtos, ele deve ser também removido na tabela dependente.

Graficamente, o relacionamento entre as três tabelas do tópico pode ser expresso como na Figura 13.17.

O tópico Fornecedores relaciona as tabelas Fornecedores, Telefones dos Fornecedores e Localidades. Um registro na tabela Fornecedores pode referir mais de um registro na tabela Telefones dos Fornecedores, devendo-se prever exclusões em cascata dos registros, já que a tabela dependente é uma tabela-filha. A tabela Localidades possui relação um-para-vários com a tabela Fornecedores, devendo-se também prever atualizações, mas não exclusões, em cascata. Graficamente, o relacionamento pode se exprimir como na Figura 13.18.

Figura 13.17: Relacionamentos do tópico Produtos.

Figura 13.18: Relacionamentos do tópico Fornecedores.

No tópico Clientes - composto pelas tabelas Clientes, Localidades e Telefones dos Clientes - o relacionamento é precisamente o mesmo que no tópico Fornecedores. Observe apenas que a tabela Localidades possui o mesmo tipo de relacionamento simultaneamente com duas tabelas. Graficamente, o relacionamento do tópico pode ser expresso como na Figura 13.19.

Continuemos. Um registro na tabela Estoque possui um relacionamento direto, de um-para-um, com um único registro da tabela Produtos. Um registro na tabela Fornecedores possui um relacionamento um-para-vários com a tabela Produtos Por Fornecedor. Em ambos os casos, deve-se impor a integridade referencial dos dados promovendo exclusões em cascata sempre que houver uma exclusão na tabela determinante da dependência.

Figura 13.19: Relacionamentos do tópico Clientes.

A tabela Produtos possui relacionamento de um-para-vários também com as tabelas Fornecimento e Transações. É conveniente impor a integridade referencial dos dados visando evitar a existência de registros órfãos nas tabelas dependentes.

Analisemos agora o tópico Vendas. Este é composto das tabelas Vendas, Faturas e Vendedores. Em primeiro lugar, devemos assinalar que entre Vendas e Faturas existe uma relação de um-para-vários - relacionamento estabelecido pelo campo Fatura - onde se deve impor integridade referencial, garantindo exclusões em cascata, sempre que um registro na tabela-pai (Vendas) for removido. Por outro lado, um registro na tabela Vendedores pode referir vários registros na tabela Vendas. Neste relacionamento, devemos impor a integridade referencial dos dados, garantindo que as eventuais alterações na tabela Vendedores se propaguem, automaticamente, para a tabela dependente. O relacionamento do tópico pode ser representado como na Figura 13.20:

Figura 13.20: Relacionamentos do tópico Vendas.

Analisemos, agora, os relacionamentos finais. Um registro na tabela de Clientes pode corresponder a vários registros na tabela de Vendas. Neste caso, devemos garantir que eventuais atualizações na tabela primária se propaguem para a tabela dependente, impondo a integridade referencial dos dados. Graficamente, o relacionamento global das diversas tabelas da base de dados pode ser representado como na Figura 13.20:

Figura 13.21: Os relacionamentos da base de dados da Limpa Tudo.

 

Localize tudo de uma vez com a localização estendida do RabJump