Esse artigo faz parte da revista SQL Magazine edição 47. Clique aqui para ler todos os artigos desta edição

Imagem

: 0cm 0cm 0pt">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

Tatiana

(34) 3822-0000

(34) 9976-0000

3

Ana

(11) 3184-0000

4

João

(31) 3257-0000

Tabela 3. Tabela Pessoa Com Atributos Multivalorados.

 

Conceito 5: Atributos Compostos

Atributos compostos são atributos que podem ser subdivididos em vários atributos.

Na Tabela 4 apresentamos a tabela Pessoa (Codigo, Nome, Endereco). Nesta tabela, o atributo endereço é multivalorado, uma vez que ele pode ser dividido em vários atributos.

 

Codigo

Nome

Endereco

1

Ary

Av. Getúlio Vargas, 1000, apto 201 – Centro – Patos de Minas-MG

2

Tatiana

Av. Brasil, 966 – Centro – Belo Horizonte-MG

3

Ana

Rua Minas Gerais, 100 – Bairro Brasil – Recife-PE

4

João

Praça da Liberdade, 27 – Bairro Esperança – São Paulo-SP

Tabela 4. Tabela Pessoa com Atributo Composto

 

Na Tabela 5 apresentamos a tabela pessoa (Codigo, Nome, TipoLogradouro, Logradouro, Nro, Comp, Bairro, Cidade, UF). Esta tabela é a mesma tabela da Tabela 4, porém com o atributo endereço sendo dividido em: Tipo de Logradouro, Logradouro, Número, Complemento, Bairro, Cidade e Estado(UF).

 

Codigo

Nome

Tipo Logradouro

Logradouro

Nro

Comp

Bairro

Cidade

UF

1

Ary

Avenida

Getúlio Vargas

1000

Apto 201

Centro

Patos de Minas

MG

2

Tatiana

Avenida

Brasil

966

 

Centro

Belo Horizonte

MG

3

Ana

Rua

Minas Gerais

100

 

Brasil

...
Quer ler esse conteúdo completo? Tenha acesso completo