artigo sql magazine 47 - Normalização de Dados
Muitos autores dizem que aplicando as três formas normais definidas por Codd, o projeto do BD já estará livre de redundâncias e inconsistências. Aqui não entraremos nesta discussão e apresentaremos todas as formas normais existentes atualmente.
Clique aqui para ler esse artigo em PDF.
Atualmente, é comum verificarmos organizações com bases de dados da ordem dos terabytes. Além disso, é sabido que a necessidade de informações por parte dos gestores é enorme e vem crescendo diariamente. Isto porque a tomada de decisões, com base em informações, torna-se muito mais precisa. E, para que estas informações sejam geradas com qualidade, é necessário um bom projeto de banco de dados.
Sabemos que o objetivo de um projeto de banco de dados é obter um conjunto de esquemas de tabelas que nos permita armazenar dados sem redundância e que as informações possam ser geradas facilmente. Para verificar se um projeto de banco de dados atende a estes pressupostos, podemos aplicar algumas regras aos projetos em questão. A estas regras, damos o nome de Formas Normais.
Originalmente, Edgar F. Codd definiu três destas formas normais (Primeira Forma Normal, Segunda Forma Normal e Terceira Forma Normal), mas hoje existem algumas outras (Forma Normal de Boyce-Codd, Quarta Forma Normal e Quinta Forma Normal) como veremos nos tópicos a seguir. Muitos autores dizem que aplicando as três formas normais definidas por Codd, o projeto do banco de dados já estará livre de redundâncias e inconsistências. Entretanto, outros autores definem como de extrema importância a aplicação das outras formas normais. Neste artigo, não entraremos nesta discussão e apresentaremos todas as formas normais existentes atualmente. Dessa forma, o leitor terá condições de verificar a importância ou não da aplicação de todas elas.
Para efetuar a normalização, aplicam-se na ordem as seguintes formas normais: primeira forma normal, segunda forma normal, terceira forma normal. Neste ponto, podemos dar continuidade à normalização seguindo pelas formas normais de Boyce-Codd, quarta forma normal e por último a Quinta Forma Normal ou, iniciar diretamente da forma normal Boyce-Codd. Estas formas normais devem ser aplicadas ao modelo de dados definido pelo profissional. Ao final da aplicação das formas normais, podemos dizer que o projeto de banco de dados está livre de redundâncias e conseqüentemente de inconsistência.
Neste momento, podemos definir normalização como sendo uma série de passos que se segue no projeto de um banco de dados que permite um armazenamento consistente e um eficiente acesso aos dados em um banco de dados relacional. Esses passos evitam a redundância de dados e as chances dos dados se tornarem inconsistentes. Devemos fazer uso destes passos sempre que estivermos projetando nossas soluções de banco de dados, salvo casos específicos onde trabalhamos com o conceito de desnormalização. Como vimos, o uso da normalização traz grandes benefícios (consistência, evita redundância, integridade) e sua não utilização poderá trazer exatamente os problemas resolvidos com normalização, ou seja: problemas de inconsistência, redundância e integridade.
Este artigo será dividido da seguinte forma: inicialmente, serão abordados conceitos importantes envolvidos no contexto. Posteriormente, serão apresentadas as formas normais e um exemplo de aplicação. Logo após, abordaremos o tópico sobre desnormalização e por último, faremos as considerações finais relacionadas ao artigo.
Conceitos importantes
Neste tópico iremos abordar alguns conceitos necessários para melhor compreensão de todo o artigo. Fiquem à vontade em retornar a este tópico sempre que alguma dúvida surgir, ou caso prefiram, podem saltar a leitura deste tópico e recorrer a ele no decorrer dos próximos tópicos. Sempre que surgir um conceito que tiver sido definido neste tópico, faremos referência a ele para que retomem a leitura a fim de revisar ou simplesmente para efetuar a leitura do conceito necessário.
Conceito 1: Dependência Funcional
Uma dependência funcional é um relacionamento entre dois ou mais atributos de forma que o valor de um atributo identifique o valor para cada um dos outros atributos, ou seja, um atributo está relacionado a outro. Por exemplo:
A à B
Nesse exemplo, o atributo B é dependente (funcionalmente) do atributo A. Em outras palavras, para ‘descobrirmos o valor de B, precisamos saber o valor de A’ (observe que a recíproca NÃO é verdadeira). Veja mais um exemplo:
Código do cliente à Nome do cliente
Nesse exemplo, para descobrirmos o nome do cliente (dentro de um conjunto de clientes), primeiramente precisamos saber qual é o código dele. Assim, o campo/atributo nome é dependente do campo/atributo código. Observe que a recíproca NÃO é verdadeira! Você poderia pensar: “Ora, eu posso conhecer o nome do cliente, e não o seu código. Nem sempre eu vou precisar saber o código do cliente para obter o nome dele”. Esse pensamento é incorreto, pois você pode ter clientes com o mesmo nome.
Outro detalhe importante é que em uma tabela podemos ter mais de uma dependência funcional. Por exemplo:
Código do cliente à Nome do cliente
Código do cliente à UF do cliente
Essa mesma afirmação pode ser descrita da seguinte forma:
Código do Cliente à [Nome do Cliente, UF do cliente]
Vamos ver agora um exemplo mais completo. Vamos supor uma tabela contendo código do cliente, nome do cliente, tipo de logradouro, logradouro, número, complemento, bairro, cidade e UF. Nesta tabela, para cada código de cliente teremos um só valor para nome do cliente, tipo de logradouro, logradouro, número, complemento, bairro, cidade e UF. Por isto, dizemos que os atributos nome do cliente, tipo de logradouro, logradouro, número, complemento, bairro, cidade e UF estão funcionalmente dependentes do código do cliente. Perceba que neste caro estamos considerando que será armazenado apenas o endereço residencial da pessoa (caso contrário, a dependência funcional deixaria de existir).
Esta dependência funcional pode ser escrita da seguinte forma:
Código à nome, tipo_logradouro, logradouro, nro, compl, bairro, cidade, UF
Com isso, podemos perceber que o valor de um atributo determina o valor de outro atributo. Provavelmente você já tenha se deparado com a forma mais comum de dependência funcional, que é gerada pela chave primária. Obviamente o valor da chave primária determina o valor dos outros atributos do mesmo registro.
Conceito 2: Dependência Funcional Parcial
Uma dependência funcional parcial ocorre quando os atributos não chave não dependam funcionalmente de toda a chave primária quando esta for composta. Assim, nas tabelas onde a chave primária for composta, todos os atributos devem depender de toda a chave primária. Caso a dependência seja de parte da chave, verificamos a existência de dependência funcional parcial.
Por exemplo:
AB à C, D
Considere que o atributo C dependa funcionalmente de A, mas não dependa de B. Já temos um exemplo de dependência funcional parcial.
Vamos ver agora um exemplo mais completo. Suponha uma tabela notas (matricula_aluno, CodDisciplina, Periodo, NomeDisciplina, Nota) (ver Tabela 1). Suponha que a chave primária desta tabela seja matricula_aluno, Periodo e CodDisciplina. Nesta tabela, verificamos que o atributo NomeDisciplina depende apenas do CodDisciplina e não depende da matrícula do aluno junto com seu período. Assim, existe uma dependência funcional parcial. Isso pode trazer problemas para o modelo como redundância de informações. Imagine que o aluno de matricula 123 tenha perdido a disciplina Engenharia de Requisitos no primeiro período e tenha que repeti-la no segundo. Perceba na Tabela 1 que neste caso teríamos o valor do campo NomeDisciplina replicado. Esta certamente não é uma boa prática de projeto. A solução neste caso seria criarmos outra tabela contendo apenas os dados da disciplina (veremos esta solução detalhadamente mais adiante quando falaremos sobre as formas normais).
Matricula_Aluno |
Periodo |
CodDisciplina |
NomeDisciplina |
Nota |
123 |
1 |
8 |
Engenharia de Requisitos |
4,0 |
123 |
1 |
9 |
Qualidade de Software |
10,0 |
123 |
1 |
5 |
Engenharia de Software |
7,0 |
123 |
2 |
8 |
Engenharia de Requisitos |
9,0 |
Tabela 1. Tabela contendo dependência funcional parcial.
Conceito 3: Dependência Funcional Transitiva
Na definição dos campos de uma entidade podem ocorrer casos em que um campo não seja dependente diretamente da chave primária ou de parte dela, mas sim dependente de outro campo da tabela, campo este que não a Chave Primária. Quando isto ocorre, dizemos que a tabela possui dependência funcional transitiva. É importante deixar claro a diferença entre dependência funcional parcial e a transitiva. Na parcial, pelo menos um atributo da tabela depende de parte da chave primária (e não dela toda); na transitiva, pelo menos um atributo da tabela depende de outro atributo que não seja chave primária.
Para definir melhor o conceito de dependência funcional transitiva, trabalharemos por meio de um exemplo. Vamos supor a existência de uma tabela funcionário contendo a matrícula do funcionário (chave primária), nome do funcionário, código do cargo, nome do cargo e salário do cargo, conforme Tabela 2.
Matricula |
NomeFuncionario |
CodCargo |
NomeCargo |
SalarioCargo |
1 |
Ary |
1 |
Professor |
R$ 7.500,00 |
2 |
Tatiana |
2 |
Advogado |
R$ 6.900,00 |
3 |
Ana |
3 |
Secretária |
R$ 1.550,00 |
4 |
Luis |
4 |
Analista de Sistemas |
R$ 8.000,00 |
5 |
Rodrigo |
1 |
Professor |
R$ 7.500,00 |
Tabela 2. Tabela Funcionário
Perceba que a matrícula do funcionário determina apenas os atributos nome do funcionário e código do cargo. Entretanto, o código do cargo (que não é chave primária) determina o nome do cargo e o salário do cargo e estes dois últimos atributos não dependem diretamente do atributo matrícula.
Matricula à NomeFuncionario, CodCargo
CodCargo à NomeCargo, SalarioCargo
Assim, temos uma dependência funcional transitiva. Perceba no exemplo da Tabela 2 que quando este tipo de dependência está presente, temos informações redundantes na tabela (o funcionário Rodrigo também é professor e possui os campos NomeCargo e SalarioCargo repetidos em relação ao funcionário Ary) e sabemos que este tipo de situação é uma das causas para a perda de integridade em projetos de banco de dados. Analisando esta situação, fica bastante claro que sabendo o valor do atributo CodCargo, saberíamos automaticamente o valor dos atributos NomeCargo, SalarioCargo e isso poderia estar armazenado em outra tabela para evitar problemas de redundância.
Conceito 4: Atributos Multivalorados
Atributos multivalorados são atributos que podem conter mais de um valor para um mesmo registro.
Na Tabela 3 apresentamos uma tabela pessoa (Codigo, Nome, Telefone). Perceba o atributo telefone para os dois primeiros registros apresentados. Existe mais de um telefone para cada pessoa. Desta forma, o atributo Telefone é multivalorado.
Codigo |
Nome |
Telefone |
1 |
Ary |
(34) 3821-0000 (34) 9979-0000 (34) 9964-0000 |
2 |
"
Artigos relacionados
-
Artigo
-
Artigo
-
Artigo
-
Artigo
-
Artigo