Normalização: teoria e formas normais

Chegamos a um dos temas que mais separam quem decorou de quem entendeu modelagem relacional. Vou te conduzir pela teoria da normalização do jeito que ela costuma ser cobrada na prova da USP: com definições rigorosas, dependências funcionais escritas em notação formal e cada forma normal acompanhada de um exemplo de violação seguido da correção. Quero que você termine este módulo capaz de olhar para uma tabela qualquer e dizer, com segurança, em qual forma normal ela está e por quê. A aplicação prática, o passo a passo de decompor um esquema real, fica para o módulo 07. Aqui o foco é a teoria — e é exatamente a teoria que cai em questões de marcar certo ou errado.

Antes de tudo, quero situar você historicamente, porque isso às vezes aparece em prova. A normalização nasce com Edgar F. Codd, o pai do modelo relacional, no artigo de 1970 “A Relational Model of Data for Large Shared Data Banks”. Codd introduziu a 1FN ali mesmo, e logo em seguida, em 1971, formulou a 2FN e a 3FN. Em 1974, junto com Raymond Boyce, propôs uma versão mais estrita da 3FN, hoje conhecida como Forma Normal de Boyce-Codd. A 4FN e a 5FN, que tratam de dependências mais sutis, vieram depois, com contribuições decisivas de Ronald Fagin sobre dependências multivaloradas e de junção. Guarde esses nomes e datas: às vezes uma questão pergunta justamente quem propôs o quê.

Por que normalizar: anomalias e redundância

Vou começar pela motivação, porque sem ela as regras viram decoreba sem sentido. Normalizar é organizar os atributos de um banco em tabelas de modo que cada fato seja armazenado uma única vez. Quando você junta numa mesma tabela informações que, na verdade, descrevem coisas diferentes, surge redundância — o mesmo dado repetido em várias linhas. E redundância não é só desperdício de espaço; ela abre a porta para três anomalias que você precisa saber nomear.

Imagine uma tabela que mistura, na mesma linha, dados do pedido e dados do produto:

ID_Pedido ID_Produto Nome_Produto Preco_Unitario Quantidade
1 P1 Lapis 1.00 10
1 P2 Caneta 2.00 5
2 P1 Lapis 1.00 8

Repare comigo que o nome “Lapis” e o preço 1.00 aparecem repetidos. Daí nascem as três anomalias clássicas.

A anomalia de atualização acontece quando você precisa mudar um valor redundante. Se o preço do lápis subir para 1.20, terá de alterar todas as linhas em que P1 aparece. Esquecer uma única linha deixa o banco inconsistente: o mesmo produto com dois preços diferentes. A anomalia de inserção ocorre quando você não consegue registrar um fato porque outro fato ainda não existe. Nessa tabela, como inserir um produto novo no catálogo se ainda não houve pedido dele? Você seria forçado a deixar ID_Pedido nulo, o que viola a integridade de chave. E a anomalia de exclusão é o espelho disso: se o pedido 2 for o único que referencia P1 e você o apagar, perde junto a informação de que o lápis custa 1.00. Apagar um fato apaga, sem querer, outro fato independente.

Definição. Normalização é o processo de decompor relações para eliminar redundância e as anomalias de inserção, atualização e exclusão, preservando a informação original. O objetivo não é ter mais tabelas por estética, mas garantir que cada fato resida em um único lugar.

flowchart TD
    A[Tabela com redundancia] --> B[Anomalia de insercao]
    A --> C[Anomalia de atualizacao]
    A --> D[Anomalia de exclusao]
    B --> E[Nao consigo registrar fato isolado]
    C --> F[Atualizo parcialmente e gero inconsistencia]
    D --> G[Apago um fato e perco outro junto]
    E --> H[Normalizar decompondo a relacao]
    F --> H
    G --> H

Dependências funcionais: a base formal de tudo

Para falar de formas normais com rigor, precisamos da linguagem das dependências funcionais. Esse é o coração formal do módulo, e é onde a notação LaTeX da prova entra. Uma dependência funcional é a afirmação de que um conjunto de atributos determina outro.

Definição formal. Seja R uma relação e X, Y subconjuntos de seus atributos. Dizemos que X determina funcionalmente Y, e escrevemos X \rightarrow Y, se para quaisquer duas tuplas t_1, t_2 \in R vale: t_1[X] = t_2[Y] \;\Rightarrow\; t_1[Y] = t_2[Y] Ou seja, sempre que duas linhas concordam no valor de X, elas obrigatoriamente concordam no valor de Y. Lê-se “X determina Y”, e X é chamado de determinante.

Uma dependência X \rightarrow Y é dita trivial quando Y \subseteq X — é o caso óbvio em que um conjunto determina a si mesmo ou parte de si. As dependências interessantes para a normalização são as não triviais, em que Y contém algum atributo fora de X. Convém também lembrar o conceito de superchave: um conjunto K tal que K \rightarrow R, isto é, K determina todos os atributos da relação. Uma chave candidata é uma superchave minimal — não dá para remover nenhum atributo dela sem perder a propriedade de determinar tudo.

A teoria nos dá um conjunto de regras de inferência, os axiomas de Armstrong, que permitem deduzir todas as dependências válidas a partir de um conjunto inicial. Vale memorizar:

Axioma Regra formal
Reflexividade Se Y \subseteq X, então X \rightarrow Y
Aumento Se X \rightarrow Y, então XZ \rightarrow YZ
Transitividade Se X \rightarrow Y e Y \rightarrow Z, então X \rightarrow Z
Decomposição Se X \rightarrow YZ, então X \rightarrow Y e X \rightarrow Z
União Se X \rightarrow Y e X \rightarrow Z, então X \rightarrow YZ
Pseudotransitividade Se X \rightarrow Y e WY \rightarrow Z, então WX \rightarrow Z

Os três primeiros são os axiomas primários; os três últimos são derivados deles. Reflexividade, aumento e transitividade bastam para gerar todo o fecho de dependências.

Total, parcial e transitiva

Três classificações de dependência são o que você usa, na prática, para decidir formas normais. Vou defini-las com precisão.

Uma dependência é total (ou completa) quando X \rightarrow Y vale, mas nenhum subconjunto próprio de X determina Y. Formalmente, Y depende totalmente de X se X \rightarrow Y e, para todo X' \subset X, temos X' \not\rightarrow Y. Numa tabela de itens de pedido com chave composta, \{Numero\_Pedido, Item\} \rightarrow Quantidade é total: a quantidade só faz sentido amarrada ao par.

Uma dependência é parcial quando Y depende apenas de parte de uma chave composta. Se a chave é \{ID\_Aluno, ID\_Curso\} e vale ID\_Aluno \rightarrow Nome\_Aluno, então o nome depende parcialmente da chave, pois não precisa do ID\_Curso. Dependências parciais são exatamente o que a 2FN proíbe.

Uma dependência é transitiva quando Y depende de X por intermédio de um atributo Z que não é chave. Se ID\_Func \rightarrow ID\_Depto e ID\_Depto \rightarrow Nome\_Depto, então por transitividade ID\_Func \rightarrow Nome\_Depto, mas essa última dependência passa por Z = ID\_Depto, que não é superchave. Dependências transitivas são o alvo da 3FN.

flowchart LR
    X[Chave X] -->|total| Y1[Atributo depende de X inteiro]
    X2[Parte da chave] -->|parcial| Y2[Atributo depende so de parte]
    Xf[ID_Func] -->|determina| Z[ID_Depto]
    Z -->|determina| W[Nome_Depto]
    Xf -.transitiva.-> W

Dependência multivalorada

Há ainda um tipo mais sutil, que sustenta a 4FN. Uma dependência multivalorada, escrita X \twoheadrightarrow Y, existe quando, para cada valor de X, há um conjunto de valores de Y que é independente dos demais atributos da relação. Formalmente, X \twoheadrightarrow Y vale em R se, dadas tuplas que concordam em X, podemos trocar livremente seus valores de Y sem gerar tuplas inválidas — os atributos Y e o resto R - X - Y são independentes dado X. Toda dependência funcional é também multivalorada, mas a recíproca não vale; a 4FN existe justamente para tratar as multivaloradas que não são funcionais.

As formas normais

Agora junto tudo. As formas normais são critérios encaixados: cada uma pressupõe a anterior e acrescenta uma exigência. Vou apresentar a hierarquia e depois detalhar cada nível com a regra exata, uma violação e a correção.

flowchart TD
    UNF[Nao normalizada] --> P1[1FN: atomicidade]
    P1 --> P2[2FN: sem dependencia parcial]
    P2 --> P3[3FN: sem dependencia transitiva]
    P3 --> BC[BCNF: todo determinante e superchave]
    BC --> Q4[4FN: sem multivalorada nao trivial]
    Q4 --> Q5[5FN: juncao implicada por chaves]

Primeira Forma Normal (1FN)

Regra (1FN). Uma relação está na 1FN se todos os seus atributos são atômicos — cada célula contém um único valor indivisível — e não há grupos repetitivos nem atributos multivalorados armazenados numa mesma coluna. Toda relação tem o mesmo conjunto de colunas para todas as tuplas.

A violação típica é guardar uma lista dentro de uma célula. Veja:

ID_Cliente Nome Telefones
1 Joao 123-4567, 987-6543
2 Maria 456-7890

A coluna Telefones quebra a atomicidade: a célula do João tem dois valores. Consultar “quem tem o telefone 987-6543” vira um exercício de manipulação de string, e não de álgebra relacional. A correção é desmembrar em linhas, uma por valor atômico:

ID_Cliente Nome Telefone
1 Joao 123-4567
1 Joao 987-6543
2 Maria 456-7890

Em SQL, a 1FN é favorecida desde a criação da tabela, quando você modela telefones como uma tabela própria:

CREATE TABLE cliente (
    id_cliente INTEGER PRIMARY KEY,
    nome       VARCHAR(100) NOT NULL
);

CREATE TABLE telefone (
    id_cliente INTEGER REFERENCES cliente(id_cliente),
    numero     VARCHAR(20),
    PRIMARY KEY (id_cliente, numero)
);

Segunda Forma Normal (2FN)

Regra (2FN). Uma relação está na 2FN se está na 1FN e nenhum atributo não-primo depende parcialmente de uma chave candidata. Em notação: para toda dependência X \rightarrow A com A não-primo, não pode existir X' \subset X com X' \rightarrow A onde X é chave. A 2FN só “morde” quando a chave é composta; com chave simples, 1FN já implica 2FN.

Veja uma tabela em 1FN com chave composta \{ID\_Pedido, ID\_Produto\}:

ID_Pedido ID_Produto Nome_Produto Quantidade
1 A Lapis 10
1 B Caneta 5
2 A Lapis 8

Aqui ID\_Produto \rightarrow Nome\_Produto: o nome do produto depende só de metade da chave. É uma dependência parcial, e é ela que faz “Lapis” se repetir. A correção decompõe em duas relações, isolando o que depende só do produto:

Pedido_Item:

ID_Pedido ID_Produto Quantidade
1 A 10
1 B 5
2 A 8

Produto:

ID_Produto Nome_Produto
A Lapis
B Caneta
CREATE TABLE produto (
    id_produto   CHAR(1) PRIMARY KEY,
    nome_produto VARCHAR(60) NOT NULL
);

CREATE TABLE pedido_item (
    id_pedido  INTEGER,
    id_produto CHAR(1) REFERENCES produto(id_produto),
    quantidade INTEGER NOT NULL,
    PRIMARY KEY (id_pedido, id_produto)
);

Terceira Forma Normal (3FN)

Regra (3FN). Uma relação está na 3FN se está na 2FN e não há dependência transitiva de atributo não-primo em relação à chave. Equivalentemente, para toda dependência funcional não trivial X \rightarrow A, ou X é superchave, ou A é atributo primo (faz parte de alguma chave candidata).

Considere funcionários em 2FN:

ID_Func Nome Departamento Gerente_Depto
1 Joao Vendas Maria
2 Pedro Marketing Carlos
3 Ana Vendas Maria

A chave é ID\_Func, mas valem ID\_Func \rightarrow Departamento e Departamento \rightarrow Gerente\_Depto. Logo Gerente\_Depto depende transitivamente da chave, passando por Departamento, que não é superchave. O sintoma é “Maria” repetida em toda linha de Vendas — e a anomalia de atualização ronda: trocar o gerente de Vendas exige mexer em várias linhas. A correção quebra a cadeia transitiva:

Funcionario:

ID_Func Nome Departamento
1 Joao Vendas
2 Pedro Marketing
3 Ana Vendas

Departamento:

Departamento Gerente_Depto
Vendas Maria
Marketing Carlos

Atenção. Há uma regrinha de bolso famosa para a 3FN: cada atributo não-chave deve depender “da chave, de toda a chave e de nada além da chave”. A primeira parte é a 1FN/integridade, a segunda é a 2FN (toda a chave, sem dependência parcial) e a terceira é a 3FN (nada além da chave, sem dependência transitiva). Use isso para checar rápido, mas na prova confirme pela definição formal.

Forma Normal de Boyce-Codd (BCNF)

Regra (BCNF). Uma relação está na BCNF se, para toda dependência funcional não trivial X \rightarrow Y válida na relação, X é uma superchave. É uma exigência mais estrita que a 3FN: a 3FN abre exceção quando Y é atributo primo, e a BCNF não abre. Toda relação em BCNF está em 3FN, mas nem toda relação em 3FN está em BCNF.

A diferença aparece quando há múltiplas chaves candidatas sobrepostas. Pense numa tabela de turmas em que cada curso tem exatamente um professor, e o professor de um curso é fixo:

ID_Curso ID_Professor Topico
C1 P1 Database
C2 P2 AI
C3 P1 Networks

Suponha as dependências ID\_Curso \rightarrow ID\_Professor e, num cenário mais rico em que um professor leciona um único curso, também ID\_Professor \rightarrow ID\_Curso. Quando temos uma dependência cujo determinante não é superchave — por exemplo ID\_Professor \rightarrow Nome\_Professor convivendo com a chave ID\_Curso — a relação pode estar em 3FN e ainda assim violar a BCNF, porque ID\_Professor determina algo sem ser superchave. A correção separa o determinante problemático em sua própria tabela:

Curso:

ID_Curso ID_Professor Topico
C1 P1 Database
C2 P2 AI
C3 P1 Networks

Professor:

ID_Professor Nome_Professor
P1 Joao
P2 Maria

Atenção. A BCNF tem um custo: nem sempre a decomposição que a alcança preserva todas as dependências funcionais. Existem esquemas em que você consegue decompor sem perda de junção (lossless) e em BCNF, mas alguma dependência original deixa de poder ser verificada dentro de uma única tabela. A 3FN, ao contrário, sempre admite decomposição que preserva dependências. Esse trade-off entre BCNF e preservação de dependências é um ponto fino que costuma aparecer em prova.

Quarta Forma Normal (4FN)

Regra (4FN). Uma relação está na 4FN se está na BCNF e não contém dependência multivalorada não trivial. Formalmente, para toda dependência multivalorada X \twoheadrightarrow Y válida e não trivial, X deve ser superchave.

A violação clássica reúne dois fatos independentes na mesma tabela. Um aluno cursa disciplinas e possui livros, e essas duas coisas não têm relação entre si:

Aluno Disciplina Livro
Joao Matematica Calculo I
Joao Matematica Algebra
Joao Fisica Calculo I
Joao Fisica Algebra

Repare no estrago: como disciplina e livro são independentes, somos forçados a fazer o produto cartesiano de todas as combinações para o João. Valem Aluno \twoheadrightarrow Disciplina e Aluno \twoheadrightarrow Livro, ambas não triviais, e Aluno não é superchave da relação inteira. A correção separa os dois fatos independentes:

Aluno_Disciplina:

Aluno Disciplina
Joao Matematica
Joao Fisica

Aluno_Livro:

Aluno Livro
Joao Calculo I
Joao Algebra

Agora cada fato vive em sua tabela e a explosão combinatória desaparece. Se quiser todas as combinações, basta um JOIN quando precisar:

SELECT ad.aluno, ad.disciplina, al.livro
FROM aluno_disciplina ad
JOIN aluno_livro al ON ad.aluno = al.aluno;

Quinta Forma Normal (5FN)

Regra (5FN). Também chamada Forma Normal de Junção-Projeção, uma relação está na 5FN se está na 4FN e toda dependência de junção nela é implicada por suas chaves candidatas. Em outras palavras, a relação não pode ser decomposta sem perda em projeções menores a menos que essa decomposição decorra das próprias chaves.

A 5FN trata de dependências de junção cíclicas entre três ou mais atributos, em que nenhuma decomposição em duas tabelas basta, mas a decomposição em três é lossless. Pense em fornecedores, produtos e projetos, com a regra de negócio de que, se um fornecedor fornece um produto, e esse produto é usado num projeto, e o fornecedor atende esse projeto, então o fornecedor fornece aquele produto para aquele projeto:

Fornecedor Produto Projeto
F1 P1 Proj1
F1 P2 Proj2
F2 P1 Proj1

A correção decompõe em três relações binárias, e a junção das três reconstrói exatamente a original — uma decomposição que duas tabelas sozinhas não conseguiriam sem perda ou sem inventar tuplas:

Forn_Produto:

Fornecedor Produto
F1 P1
F1 P2
F2 P1

Forn_Projeto:

Fornecedor Projeto
F1 Proj1
F1 Proj2
F2 Proj1

Produto_Projeto:

Produto Projeto
P1 Proj1
P2 Proj2

Atenção. A 5FN é o nível mais alto da hierarquia clássica, mas raramente é necessária na prática. Na imensa maioria dos sistemas, atingir a 3FN ou a BCNF já elimina as anomalias relevantes. A decisão de ir até 4FN ou 5FN deve pesar ganho de integridade contra custo de junções adicionais. Em prova, saiba a definição; em projeto real, normalize até onde o ganho compensa e desnormalize conscientemente quando o desempenho exigir.

Síntese comparativa

Vou consolidar tudo numa tabela que vale ouro na revisão de véspera. Cada forma normal é caracterizada pelo tipo de dependência que ela elimina:

Forma Pressupõe Elimina Condição formal
1FN Grupos repetitivos Atributos atômicos
2FN 1FN Dependência parcial A não-primo não depende de parte da chave
3FN 2FN Dependência transitiva X \rightarrow A: X superchave ou A primo
BCNF 3FN Determinante não-chave Todo X em X \rightarrow Y é superchave
4FN BCNF Multivalorada não trivial X \twoheadrightarrow Y: X superchave
5FN 4FN Junção não implicada por chaves Toda dependência de junção vem das chaves

flowchart LR
    A[1FN remove listas em celula] --> B[2FN remove dependencia parcial]
    B --> C[3FN remove dependencia transitiva]
    C --> D[BCNF exige determinante superchave]
    D --> E[4FN remove multivalorada]
    E --> F[5FN remove juncao espuria]

O que mais cai em prova. Memorize que normalização combate as três anomalias — inserção, atualização e exclusão — todas filhas da redundância. Saiba escrever e interpretar X \rightarrow Y e distinguir dependência total, parcial e transitiva, pois é nelas que se apoiam a 2FN e a 3FN. Tenha na ponta da língua a regra de bolso da 3FN: depender da chave, de toda a chave e de nada além da chave. Entenda que a BCNF é mais estrita que a 3FN e só difere quando há chaves candidatas sobrepostas, e que ela pode não preservar dependências, ao contrário da 3FN, que sempre admite decomposição preservadora. Associe a 4FN à dependência multivalorada X \twoheadrightarrow Y e a 5FN à dependência de junção. Por fim, lembre que a hierarquia é encaixada — cada forma exige a anterior — e que, na prática, a 3FN ou a BCNF costumam bastar, deixando 4FN e 5FN para cenários específicos. No módulo 07 colocaremos toda essa teoria em movimento, decompondo um esquema real passo a passo.