Normalização de bancos de dados

Olá.
Estou iniciando meu trabalho de migrar minhas postagens antigas para este meu novo blog, agora na plataforma WordPress. Como primeiro post, estou compartilhando um texto sobre normalização de bancos de dados que escrevi há quase 10 anos. Espero que seja de bom proveito.

Segundo Heuser (2001), uma Forma Normal (FN) é uma regra que deve ser obedecida por uma tabela para que ela seja considerada “bem projetada”. Existem inúmeras formas normais, ou seja, diversas regras, cada vez mais rígidas, para verificar tabelas em banco de dados relacionais. No entanto, pelo menos 3 FNs são consideradas essenciais para a construção de um bom projeto de banco de dados.

1FN (Primeira Forma Normal)

Primeira forma normal (1FN) = diz que uma tabela está na primeira forma normal quando ela não contém tabelas aninhadas

Considere a planilha a seguir:

CodProj Tipo Descr Emp
CodEmp Nome Cat Sal DataIni TempA1
LSC001 Novo Desenv. Sistema de Estoque 2146 João A1 4 01/11/1991 24
3145 Silvio A2 4 02/10/1991 24
6126 José B1 9 03/10/1992 18
1214 Carlos A2 4 04/10/1992 18
8191 Mário A1 4 01/11/1992 12
PAG02 Manutenção Sistema de RH 8191 Mário A1 4 01/05/1993 12
4112 João A2 4 01/05/1993 24
6126 José B1 9 01/11/1992 12

A planilha acima representada em um modelo relacional não normalizado (ÑN) ficaria assim:

CodProj Tipo Descr CodEmp Nome Cat Sal DataIni TempA1
LSC001 Novo Desenv. Sistema de Estoque 2146 João A1 4 01/11/1991 24
LSC001 Novo Desenv. Sistema de Estoque A2 4 02/10/1991 24
LSC001 Novo Desenv. Sistema de Estoque B1 9 03/10/1992 18
LSC001 Novo Desenv. Sistema de Estoque A2 4 04/10/1992 18
LSC001 Novo Desenv. Sistema 8191 Mário A1 4 01/11/1992 12
PAG02 Manutenção Sistema de RH 8191 Mário A1 4 01/05/1993 12
PAG02 Manutenção Manutenção 4112 João A2 4 01/05/1993 24
PAG02 Manutenção Manutenção 6126 José B1 9 01/11/1992 12

Segundo a definição da 1FN, para normalizar a tabela acima, é necessário decompô-la em duas:

Proj(CodProj, Tipo, Descr);
Emp(CodProj, CodEmp, Nome, Cat, Sal, DataIni, TempAl);

Ou seja:

Proj
CodProj Tipo Descr
LSC001 Novo Desenv. Sistema de Estoque
PAG02 Manutenção Sistema de RH
ProjEmp
CodProj CodEmp Nome Cat Sal DataIni TempA1
LSC001 2146 João A1 4 01/11/1991 24
LSC001 3145 Silvio A2 4 02/10/1991 24
LSC001 6126 José B1 9 03/10/1992 18
LSC001 1214 Carlos A2 4 04/10/1992 12
LSC001 8191 Mário A1 4 01/05/1993 12
LSC001 8191 Mário A1 4 04/01/1991 24
PAG02 4112 João A2 4 04/01/1991 24
PAG02 6126 José B1 9 01/11/1992 12

* As colunas destacadas em cinza compõem as chaves primárias.
** Vale ressaltar que se houvesse a restrição de que um funcionário só pudesse participar de exatamente 1 projeto, a chave-primária da tabela ProjEmp poderia ser composta unicamente de CodEmp.

2FN (Segunda Forma Normal)

Observando a tabela ProjEmp acima, é possível identificar que os dados do funcionário Mário se repetem em duas tuplas. É esse tipo de redundância que a 2FN visa eliminar.

Segunda Forma Normal (2FN) = uma tabela encontra-se na segunda forma normal, quando, além de estar na 1FN, não contem dependências parciais.

Dependência parcial = uma dependência parcial ocorre quando uma coluna depende apenas de parte de uma chave primária composta.

A partir das definições acima, podemos concluir que a tabela Proj já se encontra na 2FN, pois todos seus atributos dependem exclusivamente de sua chave primária, já a tabela ProjEmp não. Verifique, em ProjEmp, que atributos como Nome, Cat, Sal dependem somente de CodEmp, enquanto que DataIni, TempAl dependem da chave primária composta por inteiro (tal fato se justifica porque pode ser necessário identificar a data em que determinado usuário ingressou em um projeto). Sendo assim, para que a tabela ProjEmp fique de acordo com a 2FN, é necessário decompô-la em duas outras (ProjEmp e Emp). O projeto então fica como segue:

Proj(CodProj, Tipo, Descr);
Emp(CodProj, CodEmp, Nome, Cat, Sal, DataIni, TempAl);

Ou seja:

Proj
CodProj Tipo Descr
LSC001 Novo Desenv. Sistema de Estoque
PAG02 Manutenção Sistema de RH
ProjEmp
CodProj CodEmp DataIni TempA1
LSC001 2146 01/11/1991 24
LSC001 3145 02/10/1991 24
LSC001 6126 03/10/1992 18
LSC001 1214 04/10/1992 12
LSC001 8191 01/05/1993 12
LSC001 8191 04/01/1991 24
PAG02 4112 04/01/1991 24
PAG02 6126 01/11/1992 12
Emp
CodEmp Nome Cat Sal DataIni TempA1
2146 João A1 4 01/11/1991 24
3145 Silvio A2 4 02/10/1991 24
6126 José B1 9 03/10/1992 18
1214 Carlos A2 4 04/10/1992 12
8191 Mário A1 4 01/05/1993 12
8191 Mário A1 4 04/01/1991 24
4112 João A2 4 04/01/1991 24
6126 José B1 9 01/11/1992 12

3FN (Terceira Forma Normal)

Observando o modelo gerado aplicando-se as regras da 2FN e supondo que o salário de um empregado é determinado por sua categoria funcional (Cat), podemos notar que ainda restam dados redundantes na tabela Emp; todos os empregados da categoria A1 e A2 possuem salário 4 e B1 possuem salário 9. A 3FN visa eliminar esse tipo de redundância.

Terceira Forma Normal (3FN) = uma tabela encontra-se na terceira forma normal, quando, além de estar na 2FN, não contém dependências transitivas

Dependência transitiva = uma dependência funcional transitiva ocorre quando uma coluna, além de depender da chave primária da tabela, depende de outra coluna ou conjunto de colunas da tabela

Sendo assim, a tabela Emp obtida pela aplicação da 2FN, que contém os dados redundantes, pode ser decomposta em outras duas (Emp e Cat). O modelo fica como segue:

CodProj Tipo Descr
LSC001 Novo Desenv. Sistema de Estoque
PAG02 Manutenção Sistema de RH
ProjEmp
CodProj CodEmp DataIni TempA1
LSC001 2146 01/11/1991 24
LSC001 3145 02/10/1991 24
LSC001 6126 03/10/1992 18
LSC001 1214 04/10/1992 12
LSC001 8191 01/05/1993 12
LSC001 8191 04/01/1991 24
PAG02 4112 04/01/1991 24
PAG02 6126 01/11/1992 12
Emp
CodEmp Nome Cat
2146 João A1
3145 Silvio A2
6126 José B1
1214 Carlos A2
8191 Mário A1
8191 Mário A1
4112 João A2
6126 José B1
Cat Sal
A1 4
A2 4
B1 9

Resumo

1FN

  1. Cria-se uma tabela na 1FN referente à tabela ÑN e que contém apenas colunas com valores atômicos, isto é, sem as tabelas aninhadas;
  2. Para cada tabela aninhada, cria-se uma tabela na 1FN compostas pelas seguintes colunas:
    1. A chave primária de uma das tabelas na qual a tabela em questão está aninhada
    2. As colunas da própria tabela
  3. São definidas as chaves primárias das tabelas na 1FN que correspondem a tabelas aninhadas

2FN

  1. Copiar para a 2FN cada tabela que tenha chave primária simples ou que não tenha colunas além da chave. No caso do exemplo, é o que acontece com a tabela Proj.
  2. Para cada tabela com chave primária composta e com pelo menos uma coluna não chave (no exemplo, a tabela ProjEmp):
    • Criar na 2FN uma tabela com as chaves primárias da tabela na 1FN
    • Para cada coluna não chave fazer a seguinte pergunta:
      a coluna depende de toda a chave ou de apenas parte dela”
    • Caso a coluna dependa de toda a chave
      i. Criar a coluna correspondente na tabela com a chave completa na 2FN
    • Caso a coluna não dependa apenas de parte da chave
      i. Criar, caso ainda não existir, uma tabela na 2FN que tenha como chave primária a parte da chave que é determinante da coluna em questão
      ii. Criar a coluna dependente dentro da tabela na 2FN

3FN

Copiar para o esquema da 3FN cada tabela que tenha menos de duas colunas não chave, pois neste caso não há como haver dependências transitivas

  1. Para tabelas com duas ou mais colunas não chaves, fazer a seguinte pergunta:
    a coluna depende de alguma outra coluna não chave?”

    1. Caso dependa apenas da chave
      i. Copiar a coluna para a tabela na 3FN
    1. Caso a coluna depender de outra coluna
      i. Criar, caso ainda não exista, uma tabela no esquema na 3FN que tenha como chave primária a coluna na qual há a dependência indireta
      ii. Copiar a coluna dependente para a tabela criada
      iii. A coluna determinante deve permanecer também na tabela original

Conclusão

Quem já trabalhou com banco de dados, acaba percebendo que utilizava as FNs mesmo sem conhecê-las. Para desenvolvedores mais experientes, a eliminação de redundâncias em bancos de dados se configura uma prática essencial para o sucesso do projeto. O material utilizado para a criação deste texto menciona a 4FN, porém, para a maioria dos projetos, a 3FN é suficiente.

Bibliografia

HEUSER, Carlos Alberto. Projeto de Banco de Dados. Porto Alegre, RS: Editora Sagra Luzzatto, 2001.