Normalização
Bases de Dados
Aviso Importante
Conteúdo
O que é Normalização?
Imagine uma planilha onde uma célula contém múltiplos valores separados por barras — como armazenar vários números de itens, descrições e preços todos em uma única linha. Isso é uma tabela não normalizada, e torna a atualização, busca e manutenção de dados um pesadelo. Normalização é o processo passo a passo de reorganizar essa tabela bagunçada em um conjunto de tabelas bem estruturadas que eliminam a redundância e protegem a integridade dos dados.
O processo segue uma série de formas normais, cada uma baseada na anterior. A Primeira Forma Normal (1NF) garante que cada célula contenha um único valor atômico — sem grupos repetitivos. A Segunda Forma Normal (2NF) remove dependências parciais, onde um atributo não-chave depende de apenas parte de uma chave composta. A Terceira Forma Normal (3NF) remove dependências transitivas, onde um atributo não-chave depende de outro atributo não-chave em vez da chave primária.
Pense nisso como organizar um arquivo bagunçado: a 1NF garante que cada gaveta tenha um tipo de documento, a 2NF garante que os documentos estejam arquivados na categoria correta, e a 3NF move informações com referência cruzada para sua própria gaveta dedicada. No final, cada dado existe em exatamente um lugar — atualize uma vez e estará correto em todo lugar.
Nesta aula, vamos percorrer dois exemplos completos — um sistema de pedidos de hardware de computador e um sistema de visitas hospitalares — transformando cada um de uma única tabela caótica em um conjunto limpo de tabelas normalizadas em 3NF. Ao longo do caminho, você aprenderá a identificar chaves primárias, chaves estrangeiras, chaves compostas e as dependências que conduzem cada etapa de normalização.
UNF para 1NF — Removendo Grupos Repetitivos
Exemplo de pedido de hardware: um valor por célula, um fato por linha
Como identificar: Observe cada célula da sua tabela. Alguma célula contém mais de um valor (separados por vírgulas, barras ou listados verticalmente)? Se sim, esses atributos formam um grupo repetitivo. A correção é sempre a mesma: mova os atributos repetitivos para uma nova tabela, dê um nome significativo e vincule usando a chave primária original como chave estrangeira.
| Order No | Date | Cust No | Name | Item No | Description | Cost | Qty |
|---|---|---|---|---|---|---|---|
| 1001 | 05-Feb | 0123 | Amal | X3412/X2189 | 120Gb HD/Cisco NIC | 40/20 | 5/25 |
| 1002 | 10-Feb | 0345 | Ali | Y7674/B3456/F67584 | 17" Monitor/Wireless Mouse/2GB Ram | 50/10/80 | 6/10/7 |
| Order No | Date | Cust No | Name | Address | Contact | Item No | Description | Cost | Qty |
|---|---|---|---|---|---|---|---|---|---|
| 1001 | 05-Feb | 0123 | Amal | Dublin | 39112200 | X3412 | 120Gb HD | 40 | 5 |
| 1001 | 05-Feb | 0123 | Amal | Dublin | 39112200 | X2189 | Cisco NIC | 20 | 25 |
| 1002 | 10-Feb | 0345 | Ali | Meath | 3321001 | Y7674 | 17" Monitor | 50 | 6 |
| 1002 | 10-Feb | 0345 | Ali | Meath | 3321001 | B3456 | Wireless Mouse | 10 | 10 |
| 1002 | 10-Feb | 0345 | Ali | Meath | 3321001 | F67584 | 2GB Ram | 80 | 7 |
| Order No (PK) | Date | Cust No | Name | Address | Contact |
|---|---|---|---|---|---|
| 1001 | 05-Feb-2024 | 0123 | Amal | Dublin | 39112200 |
| 1002 | 10-Feb-2024 | 0345 | Ali | Meath | 3321001 |
| Order No (FK) | Item No (PK) | Description | Cost | Qty |
|---|---|---|---|---|
| 1001 | X3412 | 120Gb HD | 40 | 5 |
| 1001 | X2189 | Cisco NIC | 20 | 25 |
| 1002 | Y7674 | 17" Monitor | 50 | 6 |
| 1002 | B3456 | Wireless Mouse | 10 | 10 |
| 1002 | F67584 | 2GB Ram | 80 | 7 |
As colunas repetitivas de itens (laranja) são movidas para sua própria tabela. Cada item agora tem sua própria linha, e as duas tabelas são vinculadas pelo Número do Pedido.
1NF para 2NF — Removendo Dependências Parciais
Exemplo de pedido de hardware: Descrição e Custo Unitário dependem apenas do Número do Item
Como identificar: Primeiro, verifique se alguma tabela tem uma chave composta (duas ou mais colunas formando a chave primária). Se tiver, pergunte a si mesmo para cada atributo não-chave: "Este atributo precisa de AMBAS as partes da chave para ser identificado, ou apenas uma?" Se a resposta for "apenas uma", esse atributo tem uma dependência parcial e deve ser movido para sua própria tabela. Aqui, "Qual o nome do item X3412?" só precisa do Número do Item — não importa a qual pedido pertence.
| Order No (FK) | Item No (FK) | Qty |
|---|---|---|
| 1001 | X3412 | 5 |
| 1001 | X2189 | 25 |
| 1002 | Y7674 | 6 |
| 1002 | B3456 | 10 |
| 1002 | F67584 | 7 |
| Item No (PK) | Description | Unit Cost |
|---|---|---|
| X3412 | 120Gb HD | 40 |
| X2189 | Cisco NIC | 20 |
| Y7674 | 17" Monitor | 50 |
| B3456 | Wireless Mouse | 10 |
| F67584 | 2GB Ram | 80 |
Descrição e Custo Unitário são movidos para ITEM porque dependem apenas do Número do Item, não da chave composta completa.
2NF para 3NF — Removendo Dependências Transitivas
Exemplo de pedido de hardware: Nome, Endereço e Contato dependem do Número do Cliente, não do Número do Pedido
Como identificar: Para cada atributo não-chave, pergunte: "Este atributo descreve a chave primária diretamente, ou descreve outro atributo não-chave?" Se Nome descreve o Número do Cliente (não o Número do Pedido), você tem uma dependência transitiva. O teste prático: "Se eu mudar esse valor, estaria errado em outras linhas?" Se Amal mudar de Dublin para Cork, cada pedido que ela fez mostraria o endereço errado — isso significa que o endereço pertence à sua própria tabela.
| Order No (PK) | Cust No (FK) | Order Date |
|---|---|---|
| 1001 | 0123 | 05-Feb-2024 |
| 1002 | 0345 | 10-Feb-2024 |
| Cust No (PK) | Name | Address | Contact |
|---|---|---|---|
| 0123 | Amal | Dublin | 39112200 |
| 0345 | Ali | Meath | 3321001 |
| Order No (PK) | Cust No (FK) | Date |
|---|---|---|
| 1001 | 0123 | 05-Feb-2024 |
| 1002 | 0345 | 10-Feb-2024 |
| Cust No (PK) | Name | Address | Contact |
|---|---|---|---|
| 0123 | Amal | Dublin | 39112200 |
| 0345 | Ali | Meath | 3321001 |
| Item No (PK) | Description | Cost |
|---|---|---|
| X3412 | 120Gb HD | 40 |
| X2189 | Cisco NIC | 20 |
| Y7674 | 17" Monitor | 50 |
| B3456 | Wireless Mouse | 10 |
| F67584 | 2GB Ram | 80 |
| Order No (FK) | Item No (FK) | Qty |
|---|---|---|
| 1001 | X3412 | 5 |
| 1001 | X2189 | 25 |
| 1002 | Y7674 | 6 |
| 1002 | B3456 | 10 |
| 1002 | F67584 | 7 |
O resultado final em 3NF: ORDER, CUSTOMER, ITEM e ORDER_ITEM — quatro tabelas sem redundância, sem dependências parciais e sem dependências transitivas.
Pedido de Hardware — Relacionamentos entre Tabelas
Como as quatro tabelas em 3NF se conectam através de chaves estrangeiras
Sistema de Visitas Hospitalares — Passo a Passo
Aplicando o checklist de três passos a dados de saúde
| VisitID | Patient | Date | Treatments |
|---|---|---|---|
| V101 | Ali Khan | 2026-03-10 | X-Ray (Dr Smith, Radiology, €120), Blood Test (Dr John, Pathology, €50) |
| V102 | Sara Noor | 2026-03-11 | MRI Scan (Dr Lee, Imaging, €300), ECG (Dr Patel, Cardiology, €90) |
| V103 | Emma Cole | 2026-03-12 | Consulta (Dr Patel, Cardiologia, €80), Raio-X (Dr Smith, Radiologia, €120) |
| VisitID | PatientID | PatientName | Date | Treatment | Doctor | Dept | Cost |
|---|---|---|---|---|---|---|---|
| V101 | P01 | Ali Khan | 2026-03-10 | X-Ray | Dr Smith | Radiology | €120 |
| V101 | P01 | Ali Khan | 2026-03-10 | Blood Test | Dr John | Pathology | €50 |
| V102 | P02 | Sara Noor | 2026-03-11 | Ressonância | Dr Lee | Imagiologia | €300 |
| V102 | P02 | Sara Noor | 2026-03-11 | ECG | Dr Patel | Cardiologia | €90 |
| V103 | P03 | Emma Cole | 2026-03-12 | Consulta | Dr Patel | Cardiologia | €80 |
| V103 | P03 | Emma Cole | 2026-03-12 | Raio-X | Dr Smith | Radiologia | €120 |
| VisitID | PatientID | Name | Date |
|---|---|---|---|
| V101 | P01 | Ali Khan | 2026-03-10 |
| V102 | P02 | Sara Noor | 2026-03-11 |
| V103 | P03 | Emma Cole | 2026-03-12 |
| VisitID (FK) | Treatment | Doctor | Dept | Cost |
|---|---|---|---|---|
| V101 | X-Ray | Dr Smith | Radiology | €120 |
| V101 | Blood Test | Dr John | Pathology | €50 |
| V102 | Ressonância | Dr Lee | Imagiologia | €300 |
| V102 | ECG | Dr Patel | Cardiologia | €90 |
| V103 | Consulta | Dr Patel | Cardiologia | €80 |
| V103 | Raio-X | Dr Smith | Radiologia | €120 |
| PatientID | Name |
|---|---|
| P01 | Ali Khan |
| P02 | Sara Noor |
| P03 | Emma Cole |
| VisitID | PatientID (FK) | Date |
|---|---|---|
| V101 | P01 | 2026-03-10 |
| V102 | P02 | 2026-03-11 |
| V103 | P03 | 2026-03-12 |
| DoctorID | Name | Dept |
|---|---|---|
| D01 | Dr Smith | Radiology |
| D02 | Dr John | Pathology |
| D03 | Dr Lee | Imaging |
| D04 | Dr Patel | Cardiology |
| TreatmentID | Name | Cost |
|---|---|---|
| T01 | X-Ray | €120 |
| T02 | Blood Test | €50 |
| T03 | MRI Scan | €300 |
| T04 | ECG | €90 |
| T05 | Consultation | €80 |
| VisitID (FK) | TreatmentID (FK) | DoctorID (FK) |
|---|---|---|
| V101 | T01 | D01 |
| V101 | T02 | D02 |
| V102 | T03 | D03 |
| V102 | T04 | D04 |
| V103 | T05 | D04 |
| V103 | T01 | D01 |
O exemplo hospitalar produz cinco tabelas em 3NF. Cada fato é armazenado uma vez — atualizar o departamento de um médico ou o custo de um tratamento requer a alteração de apenas uma linha.
Sistema de Visitas Hospitalares — Relacionamentos entre Tabelas
Como as cinco tabelas em 3NF se conectam através de chaves estrangeiras
Como Identificar Onde Dividir Tabelas
Um checklist de decisão em três passos para cada forma normal
Procure por: Barras (X3412/X2189), listas separadas por vírgula, múltiplas linhas de dados compactadas em uma célula.
Se SIM: Primeiro, expanda cada célula com múltiplos valores em sua própria linha — você obtém uma grande tabela plana onde cada célula é atômica. Então observe a redundância (dados repetidos entre linhas) e divida os atributos repetitivos em uma nova tabela. Use a PK original como chave estrangeira na nova tabela e crie uma chave composta (PK original + PK do novo atributo).
Se NÃO: A tabela já está em 1NF — prossiga para o passo 2.
Teste: Para cada coluna não-chave, pergunte: "Preciso de AMBAS as partes da chave composta para consultar este valor?"
Se SIM (existe dep. parcial): Mova os atributos parcialmente dependentes para uma nova tabela, usando como chave a parte da qual dependem.
Se NÃO (ou sem chave composta): A tabela já está em 2NF — prossiga para o passo 3.
Teste: Para cada coluna não-chave, pergunte: "Isso descreve a PK diretamente, ou descreve uma coluna diferente?"
Teste prático: "Se eu atualizar esse valor, outras linhas ficariam inconsistentes?"
Se SIM (existe dep. transitiva): Mova os atributos transitivamente dependentes para uma nova tabela. Mantenha a coluna intermediária como FK.
Se NÃO: Parabéns — sua tabela está em 3NF!
Aplique essas três verificações em ordem a qualquer tabela. Cada passo é baseado no anterior — você deve alcançar a 1NF antes de verificar a 2NF, e a 2NF antes de verificar a 3NF.
Exemplo Prático — Sistema de Cursos de Docentes
Normalizando um horário universitário de UNF para 3NF
| Lect No | Name | Faculty | Office | Course Code | Course Name | Start Date | Weekly Hrs |
|---|---|---|---|---|---|---|---|
| 7146 | James | Business | Room 22 | BM01 | Buss Manage | 12/9/2023 | 4 |
| A01 | Account | 11/9/2023 | 3 | ||||
| E01 | Economics | 30/9/2023 | 7 | ||||
| 1463 | Denis | IT | Room 21 | CS01 | Computer Systems | 01/9/2023 | 6 |
| P01 | Programming | 02/9/2023 | 5 | ||||
| 6455 | Phil | Business | Room 22 | BM01 | Buss Manage | 04/10/2023 | 4 |
| M01 | Marketing | 10/10/2023 | 6 |
| Lect No | Name | Faculty | Office | Course Code | Course Name | Start | Hrs |
|---|---|---|---|---|---|---|---|
| 7146 | James | Business | Room 22 | BM01 | Buss Manage | 12/9/23 | 4 |
| 7146 | James | Business | Room 22 | A01 | Account | 11/9/23 | 3 |
| 7146 | James | Business | Room 22 | E01 | Economics | 30/9/23 | 7 |
| 1463 | Denis | IT | Room 21 | CS01 | Comp Systems | 01/9/23 | 6 |
| 1463 | Denis | IT | Room 21 | P01 | Programming | 02/9/23 | 5 |
| 6455 | Phil | Business | Room 22 | BM01 | Buss Manage | 04/10/23 | 4 |
| 6455 | Phil | Business | Room 22 | M01 | Marketing | 10/10/23 | 6 |
| Lect No (PK) | Name | Faculty | Office |
|---|---|---|---|
| 7146 | James | Business | Room 22 |
| 1463 | Denis | IT | Room 21 |
| 6455 | Phil | Business | Room 22 |
| Lect No (FK) | Course Code | Course Name | Start | Hrs |
|---|---|---|---|---|
| 7146 | BM01 | Buss Manage | 12/9/23 | 4 |
| 7146 | A01 | Account | 11/9/23 | 3 |
| 7146 | E01 | Economics | 30/9/23 | 7 |
| 1463 | CS01 | Comp Systems | 01/9/23 | 6 |
| 1463 | P01 | Programming | 02/9/23 | 5 |
| 6455 | BM01 | Buss Manage | 04/10/23 | 4 |
| 6455 | M01 | Marketing | 10/10/23 | 6 |
| Code (PK) | Name |
|---|---|
| BM01 | Buss Manage |
| A01 | Account |
| E01 | Economics |
| CS01 | Comp Systems |
| P01 | Programming |
| M01 | Marketing |
| Lect No (FK) | Code (FK) | Start Date | Weekly Hrs |
|---|---|---|---|
| 7146 | BM01 | 12/9/23 | 4 |
| 7146 | A01 | 11/9/23 | 3 |
| 7146 | E01 | 30/9/23 | 7 |
| 1463 | CS01 | 01/9/23 | 6 |
| 1463 | P01 | 02/9/23 | 5 |
| 6455 | BM01 | 04/10/23 | 4 |
| 6455 | M01 | 10/10/23 | 6 |
| Lect No (PK) | Name | Faculty | Office |
|---|---|---|---|
| 7146 | James | Business | Room 22 |
| 1463 | Denis | IT | Room 21 |
| 6455 | Phil | Business | Room 22 |
| Code (PK) | Name |
|---|---|
| BM01 | Buss Manage |
| A01 | Account |
| E01 | Economics |
| CS01 | Comp Systems |
| P01 | Programming |
| M01 | Marketing |
| Lect No (FK) | Code (FK) | Start | Hrs |
|---|---|---|---|
| 7146 | BM01 | 12/9/23 | 4 |
| 7146 | A01 | 11/9/23 | 3 |
| 7146 | E01 | 30/9/23 | 7 |
| 1463 | CS01 | 01/9/23 | 6 |
| 1463 | P01 | 02/9/23 | 5 |
| 6455 | BM01 | 04/10/23 | 4 |
| 6455 | M01 | 10/10/23 | 6 |
O exemplo do docente usa o mesmo checklist de três passos. Course Name tinha uma dependência parcial de Course Code, mas nenhuma dependência transitiva foi encontrada — a 3NF foi alcançada no passo 2.
Sistema de Cursos de Docentes — Relacionamentos entre Tabelas
Como as três tabelas em 3NF se conectam através de chaves estrangeiras
SQL — Passo 1: UNF para 1NF
Dividir a tabela ORDER única em ORDER + ORDER_ITEM
-- STEP 1: UNF → 1NF -- Remove repeating groups (item details) into a new table CREATE TABLE "Order" ( order_number INT PRIMARY KEY, order_date DATE NOT NULL, customer_number VARCHAR(4) NOT NULL, name VARCHAR(50) NOT NULL, address VARCHAR(100) NOT NULL, contact_number VARCHAR(20) NOT NULL ); -- New table for the repeating item group -- Composite key: order_number + item_number CREATE TABLE Order_Item ( order_number INT REFERENCES "Order", item_number VARCHAR(10) NOT NULL, description VARCHAR(100) NOT NULL, unit_cost DECIMAL(10,2) NOT NULL, quantity INT NOT NULL, PRIMARY KEY (order_number, item_number) );
SQL — Passo 2: 1NF para 2NF
Extrair tabela ITEM para remover dependência parcial
-- STEP 2: 1NF → 2NF -- Description and unit_cost depend only on item_number -- (partial dependency on the composite key) -- Move them to a new ITEM table CREATE TABLE Item ( item_number VARCHAR(10) PRIMARY KEY, description VARCHAR(100) NOT NULL, unit_cost DECIMAL(10,2) NOT NULL ); -- Order_Item now only keeps quantity -- (depends on the FULL composite key) CREATE TABLE Order_Item ( order_number INT REFERENCES "Order", item_number VARCHAR(10) REFERENCES Item, quantity INT NOT NULL, PRIMARY KEY (order_number, item_number) );
SQL — Passo 3: 2NF para 3NF
Extrair tabela CUSTOMER para remover dependência transitiva
-- STEP 3: 2NF → 3NF -- Name, address and contact depend on customer_number -- (transitive dependency — not on the PK) -- Move them to a new CUSTOMER table CREATE TABLE Customer ( customer_number VARCHAR(4) PRIMARY KEY, name VARCHAR(50) NOT NULL, address VARCHAR(100) NOT NULL, contact_number VARCHAR(20) NOT NULL ); -- Order now only keeps customer_number as FK CREATE TABLE "Order" ( order_number INT PRIMARY KEY, customer_number VARCHAR(4) REFERENCES Customer, order_date DATE NOT NULL ); -- Final schema: 4 tables in 3NF -- Customer, Order, Item, Order_Item -- Each fact stored exactly once ✓
Referência Rápida
| Conceito | Regra | O que Fazer |
|---|---|---|
| UNF | Dados brutos, pode ter grupos repetitivos | Identificar entidade, listar todos os atributos, encontrar a chave |
| 1NF | Sem atributos multivalorados | Remover grupos repetitivos para uma nova tabela; adicionar uma chave estrangeira para vinculá-los |
| 2NF | Sem dependências parciais | Se existe uma chave composta, mover atributos que dependem de apenas parte dela |
| 3NF | Sem dependências transitivas | Mover atributos não-chave que dependem de outros atributos não-chave |
| Chave Primária (PK) | Identifica cada linha de forma única | Não pode ser NULL; sublinhada na notação |
| Chave Estrangeira (FK) | Referencia uma PK em outra tabela | Cria relacionamentos entre tabelas |
| Chave Composta | Dois ou mais atributos formando uma PK | Usada quando nenhum atributo único é exclusivo (ex.: Nº Pedido + Nº Item) |
Exercícios Práticos
Teste seu entendimento sobre normalização
Lecturer_no, Name, Faculty, Office_loc, Course_code, Course_name, Start_date, Weekly_time. Um docente leciona múltiplos cursos. Quais são os atributos repetitivos (multivalorados)?| LoanID | MemberName | MemberEmail | BookTitle | Author | LoanDate | ReturnDate |
|---|---|---|---|---|---|---|
| L01 | Jane Doe | jane@mail.com | SQL Basics | T. Brown | 01/03/26 | 15/03/26 |
| L02 | Jane Doe | jane@mail.com | Data Design | R. Singh | 05/03/26 | 19/03/26 |
| L03 | Mark Lee | mark@mail.com | SQL Basics | T. Brown | 10/03/26 | 24/03/26 |
| BookingID | Client | Phone | Class | Instructor | Inst Phone | Room | Date |
|---|---|---|---|---|---|---|---|
| B01 | Anna | 555-1234 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B02 | Tom | 555-5678 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B03 | Anna | 555-1234 | Pilates | Coach Lee | 555-8888 | R2 | 11/03/26 |
| PurchID | CustEmail | CustName | Product | Category | CatDiscount | Qty | Date |
|---|---|---|---|---|---|---|---|
| P01 | jo@mail.com | Jo | Keyboard | Peripherals | 10% | 2 | 01/03/26 |
| P02 | jo@mail.com | Jo | Monitor | Displays | 5% | 1 | 02/03/26 |
| P03 | sam@mail.com | Sam | Mouse | Peripherals | 10% | 3 | 03/03/26 |
| ReservID | Guest | GuestEmail | CheckIn | RoomNo | RoomType | Rate | Services |
|---|---|---|---|---|---|---|---|
| R01 | Liam | liam@mail.com | 01/03 | 101 | Single | €80 | Breakfast €15, Spa €40 |
| R02 | Mia | mia@mail.com | 02/03 | 205 | Double | €120 | Breakfast €15, Gym €10, Laundry €25 |
| R03 | Liam | liam@mail.com | 10/03 | 101 | Single | €80 | Gym €10 |
| StudentID | Name | Address | DeptCode | DeptName | Modules |
|---|---|---|---|---|---|
| S001 | Ava | Dublin | CS | Comp Sci | M101 Databases (Dr Ryan, B+), M102 Networks (Dr Kelly, A) |
| S002 | Noah | Cork | CS | Comp Sci | M101 Databases (Dr Ryan, A-), M103 Web Dev (Dr Murphy, B) |
| S003 | Ella | Galway | BA | Business | M201 Marketing (Dr Walsh, A), M101 Databases (Dr Ryan, B+) |
Respostas
| LoanID | MemberName | MemberEmail | BookTitle | Author | LoanDate | ReturnDate |
|---|---|---|---|---|---|---|
| L01 | Jane Doe | jane@mail.com | SQL Basics | T. Brown | 01/03/26 | 15/03/26 |
| L02 | Jane Doe | jane@mail.com | Data Design | R. Singh | 05/03/26 | 19/03/26 |
| L03 | Mark Lee | mark@mail.com | SQL Basics | T. Brown | 10/03/26 | 24/03/26 |
| LoanID | MemberName | MemberEmail | BookTitle | Author | LoanDate | ReturnDate |
|---|---|---|---|---|---|---|
| L01 | Jane Doe | jane@mail.com | SQL Basics | T. Brown | 01/03/26 | 15/03/26 |
| L02 | Jane Doe | jane@mail.com | Data Design | R. Singh | 05/03/26 | 19/03/26 |
| L03 | Mark Lee | mark@mail.com | SQL Basics | T. Brown | 10/03/26 | 24/03/26 |
| LoanID | MemberName | MemberEmail | BookTitle | Author | LoanDate | ReturnDate |
|---|---|---|---|---|---|---|
| L01 | Jane Doe | jane@mail.com | SQL Basics | T. Brown | 01/03/26 | 15/03/26 |
| L02 | Jane Doe | jane@mail.com | Data Design | R. Singh | 05/03/26 | 19/03/26 |
| L03 | Mark Lee | mark@mail.com | SQL Basics | T. Brown | 10/03/26 | 24/03/26 |
• MemberName & MemberEmail depend on the member, não de LoanID — dependência transitiva.
• BookTitle & Author depend on the book, não de LoanID — dependência transitiva.
Correção: extract MEMBER and BOOK tables.
| MemberID | MemberName | MemberEmail |
|---|---|---|
| M01 | Jane Doe | jane@mail.com |
| M02 | Mark Lee | mark@mail.com |
| BookID | BookTitle | Author |
|---|---|---|
| B01 | SQL Basics | T. Brown |
| B02 | Data Design | R. Singh |
| LoanID | MemberID (FK) | BookID (FK) | LoanDate | ReturnDate |
|---|---|---|---|---|
| L01 | M01 | B01 | 01/03/26 | 15/03/26 |
| L02 | M01 | B02 | 05/03/26 | 19/03/26 |
| L03 | M02 | B01 | 10/03/26 | 24/03/26 |
| BookingID | Client | Phone | Class | Instructor | Inst Phone | Room | Date |
|---|---|---|---|---|---|---|---|
| B01 | Anna | 555-1234 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B02 | Tom | 555-5678 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B03 | Anna | 555-1234 | Pilates | Coach Lee | 555-8888 | R2 | 11/03/26 |
| BookingID | Client | Phone | Class | Instructor | Inst Phone | Room | Date |
|---|---|---|---|---|---|---|---|
| B01 | Anna | 555-1234 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B02 | Tom | 555-5678 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B03 | Anna | 555-1234 | Pilates | Coach Lee | 555-8888 | R2 | 11/03/26 |
| BookingID | Client | Phone | Class | Instructor | Inst Phone | Room | Date |
|---|---|---|---|---|---|---|---|
| B01 | Anna | 555-1234 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B02 | Tom | 555-5678 | Yoga | Coach Kim | 555-9999 | R1 | 10/03/26 |
| B03 | Anna | 555-1234 | Pilates | Coach Lee | 555-8888 | R2 | 11/03/26 |
• Phone depends on Client, not on BookingID — transitive dependency (Anna's phone repeats in B01 & B03).
• Instructor, Inst Phone & Room depend on Class, not on BookingID — transitive dependency (Yoga is always Coach Kim in R1).
• Inst Phone depends on Instructor, not on Class — another transitive dependency (Coach Kim's phone describes the instructor).
Correção: extract CLIENT, INSTRUCTOR, and CLASS tables.
| ClientID | ClientName | Phone |
|---|---|---|
| C01 | Anna | 555-1234 |
| C02 | Tom | 555-5678 |
| InstructorID | Name | Phone |
|---|---|---|
| I01 | Coach Kim | 555-9999 |
| I02 | Coach Lee | 555-8888 |
| ClassID | ClassName | InstructorID (FK) | Room |
|---|---|---|---|
| CL01 | Yoga | I01 | R1 |
| CL02 | Pilates | I02 | R2 |
| BookingID | ClientID (FK) | ClassID (FK) | Date |
|---|---|---|---|
| B01 | C01 | CL01 | 10/03/26 |
| B02 | C02 | CL01 | 10/03/26 |
| B03 | C01 | CL02 | 11/03/26 |
| PurchID | CustEmail | CustName | Product | Category | CatDiscount | Qty | Date |
|---|---|---|---|---|---|---|---|
| P01 | jo@mail.com | Jo | Keyboard | Peripherals | 10% | 2 | 01/03/26 |
| P02 | jo@mail.com | Jo | Monitor | Displays | 5% | 1 | 02/03/26 |
| P03 | sam@mail.com | Sam | Mouse | Peripherals | 10% | 3 | 03/03/26 |
| PurchID | CustEmail | CustName | Product | Category | CatDiscount | Qty | Date |
|---|---|---|---|---|---|---|---|
| P01 | jo@mail.com | Jo | Keyboard | Peripherals | 10% | 2 | 01/03/26 |
| P02 | jo@mail.com | Jo | Monitor | Displays | 5% | 1 | 02/03/26 |
| P03 | sam@mail.com | Sam | Mouse | Peripherals | 10% | 3 | 03/03/26 |
| PurchID | CustEmail | CustName | Product | Category | CatDiscount | Qty | Date |
|---|---|---|---|---|---|---|---|
| P01 | jo@mail.com | Jo | Keyboard | Peripherals | 10% | 2 | 01/03/26 |
| P02 | jo@mail.com | Jo | Monitor | Displays | 5% | 1 | 02/03/26 |
| P03 | sam@mail.com | Sam | Mouse | Peripherals | 10% | 3 | 03/03/26 |
• CustName depends on CustEmail, not on PurchID — transitive dependency (Jo's name repeats whenever jo@mail.com appears).
• Category depends on Product, not on PurchID — transitive dependency (Keyboard is always Peripherals).
• CatDiscount depends on Category, not on Product — this is a cadeia transitiva dupla: PurchID → Product → Category → CatDiscount (10% belongs to all Peripherals, not per product).
Correção: extract CUSTOMER, CATEGORY, and PRODUCT tables.
| CustID | CustEmail | CustName |
|---|---|---|
| C01 | jo@mail.com | Jo |
| C02 | sam@mail.com | Sam |
| CatID | CatName | CatDiscount |
|---|---|---|
| CAT01 | Peripherals | 10% |
| CAT02 | Displays | 5% |
| ProdID | ProdName | CatID (FK) |
|---|---|---|
| PR01 | Keyboard | CAT01 |
| PR02 | Monitor | CAT02 |
| PR03 | Mouse | CAT01 |
| PurchID | CustID (FK) | ProdID (FK) | Qty | Date |
|---|---|---|---|---|
| P01 | C01 | PR01 | 2 | 01/03/26 |
| P02 | C01 | PR02 | 1 | 02/03/26 |
| P03 | C02 | PR03 | 3 | 03/03/26 |
| ReservID | Guest | GuestEmail | CheckIn | RoomNo | RoomType | Rate | Services |
|---|---|---|---|---|---|---|---|
| R01 | Liam | liam@mail.com | 01/03 | 101 | Single | €80 | Breakfast €15, Spa €40 |
| R02 | Mia | mia@mail.com | 02/03 | 205 | Double | €120 | Breakfast €15, Gym €10, Laundry €25 |
| R03 | Liam | liam@mail.com | 10/03 | 101 | Single | €80 | Gym €10 |
| ReservID | Guest | GuestEmail | CheckIn | RoomNo | RoomType | Rate | ServiceName | ServicePrice |
|---|---|---|---|---|---|---|---|---|
| R01 | Liam | liam@mail.com | 01/03 | 101 | Single | €80 | Breakfast | €15 |
| R01 | Liam | liam@mail.com | 01/03 | 101 | Single | €80 | Spa | €40 |
| R02 | Mia | mia@mail.com | 02/03 | 205 | Double | €120 | Breakfast | €15 |
| R02 | Mia | mia@mail.com | 02/03 | 205 | Double | €120 | Gym | €10 |
| R02 | Mia | mia@mail.com | 02/03 | 205 | Double | €120 | Laundry | €25 |
| R03 | Liam | liam@mail.com | 10/03 | 101 | Single | €80 | Gym | €10 |
| ReservID | Guest | GuestEmail | CheckIn | RoomNo | RoomType | Rate |
|---|---|---|---|---|---|---|
| R01 | Liam | liam@mail.com | 01/03 | 101 | Single | €80 |
| R02 | Mia | mia@mail.com | 02/03 | 205 | Double | €120 |
| R03 | Liam | liam@mail.com | 10/03 | 101 | Single | €80 |
| ReservID | ServiceName | Price |
|---|---|---|
| R01 | Breakfast | €15 |
| R01 | Spa | €40 |
| R02 | Breakfast | €15 |
| R02 | Gym | €10 |
| R02 | Laundry | €25 |
| R03 | Gym | €10 |
| ServiceID | ServiceName | Price |
|---|---|---|
| SV01 | Breakfast | €15 |
| SV02 | Spa | €40 |
| SV03 | Gym | €10 |
| SV04 | Laundry | €25 |
| ReservID (FK) | ServiceID (FK) |
|---|---|
| R01 | SV01 |
| R01 | SV02 |
| R02 | SV01 |
| R02 | SV03 |
| R02 | SV04 |
| R03 | SV03 |
| GuestID | GuestName | GuestEmail |
|---|---|---|
| G01 | Liam | liam@mail.com |
| G02 | Mia | mia@mail.com |
| RoomNo | RoomType | Rate |
|---|---|---|
| 101 | Single | €80 |
| 205 | Double | €120 |
| ReservID | GuestID (FK) | RoomNo (FK) | CheckIn |
|---|---|---|---|
| R01 | G01 | 101 | 01/03 |
| R02 | G02 | 205 | 02/03 |
| R03 | G01 | 101 | 10/03 |
| ReservID (FK) | ServiceID (FK) |
|---|---|
| R01 | SV01 |
| R01 | SV02 |
| R02 | SV01 |
| R02 | SV03 |
| R02 | SV04 |
| R03 | SV03 |
| StudentID | Name | Address | DeptCode | DeptName | Modules |
|---|---|---|---|---|---|
| S001 | Ava | Dublin | CS | Comp Sci | M101 Databases (Dr Ryan, B+), M102 Networks (Dr Kelly, A) |
| S002 | Noah | Cork | CS | Comp Sci | M101 Databases (Dr Ryan, A-), M103 Web Dev (Dr Murphy, B) |
| S003 | Ella | Galway | BA | Business | M201 Marketing (Dr Walsh, A), M101 Databases (Dr Ryan, B+) |
| StudentID | Name | Address | DeptCode | DeptName | ModCode | ModName | Lecturer | Grade |
|---|---|---|---|---|---|---|---|---|
| S001 | Ava | Dublin | CS | Comp Sci | M101 | Databases | Dr Ryan | B+ |
| S001 | Ava | Dublin | CS | Comp Sci | M102 | Networks | Dr Kelly | A |
| S002 | Noah | Cork | CS | Comp Sci | M101 | Databases | Dr Ryan | A- |
| S002 | Noah | Cork | CS | Comp Sci | M103 | Web Dev | Dr Murphy | B |
| S003 | Ella | Galway | BA | Business | M201 | Marketing | Dr Walsh | A |
| S003 | Ella | Galway | BA | Business | M101 | Databases | Dr Ryan | B+ |
| StudentID | Name | Address | DeptCode | DeptName |
|---|---|---|---|---|
| S001 | Ava | Dublin | CS | Comp Sci |
| S002 | Noah | Cork | CS | Comp Sci |
| S003 | Ella | Galway | BA | Business |
| StudentID | ModCode | ModName | Lecturer | Grade |
|---|---|---|---|---|
| S001 | M101 | Databases | Dr Ryan | B+ |
| S001 | M102 | Networks | Dr Kelly | A |
| S002 | M101 | Databases | Dr Ryan | A- |
| S002 | M103 | Web Dev | Dr Murphy | B |
| S003 | M201 | Marketing | Dr Walsh | A |
| S003 | M101 | Databases | Dr Ryan | B+ |
| ModCode | ModName | Lecturer |
|---|---|---|
| M101 | Databases | Dr Ryan |
| M102 | Networks | Dr Kelly |
| M103 | Web Dev | Dr Murphy |
| M201 | Marketing | Dr Walsh |
| StudentID (FK) | ModCode (FK) | Grade |
|---|---|---|
| S001 | M101 | B+ |
| S001 | M102 | A |
| S002 | M101 | A- |
| S002 | M103 | B |
| S003 | M201 | A |
| S003 | M101 | B+ |
| DeptCode | DeptName |
|---|---|
| CS | Comp Sci |
| BA | Business |
| StudentID | Name | Address | DeptCode (FK) |
|---|---|---|---|
| S001 | Ava | Dublin | CS |
| S002 | Noah | Cork | CS |
| S003 | Ella | Galway | BA |
| ModCode | ModName | Lecturer |
|---|---|---|
| M101 | Databases | Dr Ryan |
| M102 | Networks | Dr Kelly |
| M103 | Web Dev | Dr Murphy |
| M201 | Marketing | Dr Walsh |
| StudentID (FK) | ModCode (FK) | Grade |
|---|---|---|
| S001 | M101 | B+ |
| S001 | M102 | A |
| S002 | M101 | A- |
| S002 | M103 | B |
| S003 | M201 | A |
| S003 | M101 | B+ |
Referências
Fontes utilizadas na elaboração deste material
Bons estudos!
Bancos de dados são a base de toda aplicação moderna