Data modeling is the process of describing how data is organized, connected, and constrained before building a database.
Why Data Modeling Matters
A data model helps teams agree on:
What data must be stored
How different concepts relate
Which rules protect data quality
How the database supports real questions
From Real World to Database
Data modeling translates real-world objects and processes into database structures.
flowchart LR
A[Real-world process] --> B[Conceptual model]
B --> C[Logical model]
C --> D[Physical database]
classDef blue fill:#0072B2,color:#FFFFFF,stroke:#111111,stroke-width:2px
classDef orange fill:#E69F00,color:#000000,stroke:#111111,stroke-width:2px
classDef green fill:#009E73,color:#000000,stroke:#111111,stroke-width:2px
classDef purple fill:#CC79A7,color:#000000,stroke:#111111,stroke-width:2px
class A blue
class B orange
class C green
class D purple
Three Levels of Data Models
Level
Main question
Typical output
Conceptual
What does the organization need to track?
Entities and relationships
Logical
How should the data be structured?
Tables, columns, keys, and constraints
Physical
How will the DBMS store and access it?
Data types, indexes, and storage choices
Entity-Relationship Diagrams
An Entity-Relationship diagram, or ER diagram, visually represents:
Entities
Attributes
Relationships
Cardinality rules
Entities
An entity is a thing about which we want to store data.
Examples:
Student
Course
Instructor
Enrollment
Product
Order
Attributes
An attribute is a fact or property stored about an entity.
For a Student entity, attributes might include:
student_id
first_name
last_name
email
major
Activity: Identify Entities and Attributes
Scenario: A college wants to track students, courses, instructors, departments, and course enrollments.
Time: 8 minutes Deliverable: A labeled list containing:
At least 3 entities
At least 2 attributes per entity
Relationships
A relationship describes how entities are connected.
Examples:
A student enrolls in a course
An instructor teaches a course
A department offers many courses
An order contains products
Cardinality
Cardinality describes how many records can participate in a relationship.
Common types:
One-to-one
One-to-many
Many-to-many
One-to-One Relationship
A one-to-one relationship means one record in Entity A is associated with one record in Entity B.
erDiagram
PERSON ||--|| PASSPORT : has
PERSON {
int person_id
string full_name
}
PASSPORT {
int passport_id
string passport_number
}
One-to-Many Relationship
A one-to-many relationship means one record in Entity A can be associated with many records in Entity B.
erDiagram
DEPARTMENT ||--o{ COURSE : offers
DEPARTMENT {
int department_id
string department_name
}
COURSE {
int course_id
string course_name
}
Many-to-Many Relationship
A many-to-many relationship means many records in Entity A can connect to many records in Entity B.
Example:
Many students can enroll in many courses
Many products can appear in many orders
Activity: Draw Cardinality
For each statement, decide the cardinality:
A department has many instructors.
A student has one university ID card.
A student enrolls in many courses, and a course has many students.
A customer places many orders.
Then sketch a simple ER diagram for each. Label each relationship with a verb.
Resolving Many-to-Many Relationships
Many-to-many relationships are usually resolved with a bridge table, also called an associative table.
flowchart LR
S[Student] --> E[Enrollment]
E --> C[Course]
classDef blue fill:#0072B2,color:#FFFFFF,stroke:#111111,stroke-width:2px
classDef orange fill:#E69F00,color:#000000,stroke:#111111,stroke-width:2px
classDef green fill:#009E73,color:#000000,stroke:#111111,stroke-width:2px
class S blue
class E orange
class C green
Example ER Diagram: Course Enrollment
erDiagram
DEPARTMENT ||--o{ COURSE : offers
INSTRUCTOR ||--o{ COURSE : teaches
STUDENT ||--o{ ENROLLMENT : completes
COURSE ||--o{ ENROLLMENT : includes
DEPARTMENT {
int department_id
string department_name
}
INSTRUCTOR {
int instructor_id
string full_name
}
STUDENT {
int student_id
string full_name
}
COURSE {
int course_id
string course_name
}
ENROLLMENT {
int enrollment_id
date enrolled_on
string final_grade
}
Keys
Data Modeling
Keys
Normalization
Keys in Relational Databases
Keys help identify records and connect tables.
Key type
Purpose
Example
Primary key
Uniquely identifies a row
student_id in Student
Foreign key
References a row in another table
student_id in Enrollment
Composite key
Uses multiple columns for uniqueness
(student_id, course_id, term)
Candidate key
Could serve as the primary key
A verified, unique email address
Primary Keys
A primary key uniquely identifies each row in a table.
A good primary key should be:
Unique
Not missing
Stable over time
Simple to reference
Primary Key Example
student_id
first_name
last_name
email
101
Ana
Rivera
ana@example.edu
102
Jamal
Lee
jamal@example.edu
103
Mei
Chen
mei@example.edu
student_id is the primary key because it uniquely identifies each student.
Foreign Keys
A foreign key is a field in one table that refers to the primary key in another table.
Foreign keys are used to:
Connect related tables
Enforce valid relationships
Prevent orphan records
Primary and Foreign Keys Together
flowchart LR
D[Department table\ndepartment_id is primary key] --> C[Course table\ndepartment_id is foreign key]
classDef blue fill:#0072B2,color:#FFFFFF,stroke:#111111,stroke-width:2px
classDef orange fill:#E69F00,color:#000000,stroke:#111111,stroke-width:2px
class D blue
class C orange
Activity: Find the Keys
Given these tables, identify the primary keys and foreign keys.
A composite key uses two or more columns together to uniquely identify a row.
Example:
Enrollment(student_id, course_id, term)
Together, these fields can identify one student’s enrollment in one course during one term.
Normalization
Data Modeling
Keys
Normalization
Why Normalize Data?
Normalization stores each fact in the table where it belongs.
Problem
Example
Risk
Repeated data
A customer’s name appears on every order line
Updates can disagree
Insert anomaly
A product cannot be recorded until someone orders it
Valid facts cannot be stored
Delete anomaly
Deleting the final order removes the only product record
Valid facts disappear
Normal Forms at a Glance
Normal form
Requirement
Question to ask
1NF
Atomic values and no repeating groups
Does each cell contain one value?
2NF
1NF plus no partial dependencies
Does each non-key field depend on the whole key?
3NF
2NF plus no transitive dependencies
Does a non-key field depend on another non-key field?
First Normal Form
A table satisfies first normal form when:
Each cell contains one value
Each column describes one type of fact
Each row has a unique identifier
Repeating column groups do not appear
flowchart LR
A[Product 1 and Product 2 columns] --> B[One product per row]
B --> C[Composite row key]
classDef red fill:#D55E00,color:#FFFFFF,stroke:#111111,stroke-width:2px
classDef yellow fill:#F0E442,color:#000000,stroke:#111111,stroke-width:2px
classDef green fill:#009E73,color:#000000,stroke:#111111,stroke-width:2px
class A red
class B yellow
class C green
Order Dataset Normalization
An online store records customers, orders, products, and quantities.
Business rules
One customer can place many orders
One order can contain many products
A product can appear on many orders
Quantity describes one product on one order
Normalization Process
flowchart LR
A[Unnormalized dataset] --> B[1NF: one value per cell]
B --> C[2NF: remove partial dependencies]
C --> D[3NF: remove transitive dependencies]
classDef red fill:#D55E00,color:#FFFFFF,stroke:#111111,stroke-width:2px
classDef yellow fill:#F0E442,color:#000000,stroke:#111111,stroke-width:2px
classDef blue fill:#0072B2,color:#FFFFFF,stroke:#111111,stroke-width:2px
classDef green fill:#009E73,color:#000000,stroke:#111111,stroke-width:2px
class A red
class B yellow
class C blue
class D green
quantity depends on the complete key. Several other fields depend on only part of the key.
Partial Dependencies in the 1NF Table
The key is (order_id, product_id).
order_date, customer_id, and customer_name depend on order_id
product_name and unit_price depend on product_id
quantity depends on both key columns
Separating order facts and product facts removes the partial dependencies.
Step 2: Orders Table in 2NF
Orders_2NF
order_id (PK)
order_date
customer_id
customer_name
1001
2026-09-01
C01
Ana Rivera
1002
2026-09-02
C02
Jamal Lee
1003
2026-09-03
C01
Ana Rivera
All fields depend on the complete primary key, order_id.
Step 2: Products Table in 2NF
Products
product_id (PK)
product_name
unit_price
P10
USB-C Hub
29.99
P20
Wireless Mouse
24.50
P30
Laptop Stand
39.00
Each product name and price now appears once.
Step 2: Order Items Table in 2NF
Order_Items
order_id (PK, FK)
product_id (PK, FK)
quantity
1001
P10
1
1001
P20
2
1002
P10
1
1003
P30
1
1003
P20
1
The composite primary key is (order_id, product_id).
Transitive Dependency in the 2NF Design
Inside Orders_2NF:
order_id -> customer_id -> customer_name
customer_name depends on customer_id, a non-key field.
Moving customer details into a separate table removes this transitive dependency.
Step 3: Customers Table in 3NF
Customers
customer_id (PK)
customer_name
C01
Ana Rivera
C02
Jamal Lee
The table stores each customer name once.
Step 3: Orders Table in 3NF
Orders
order_id (PK)
order_date
customer_id (FK)
1001
2026-09-01
C01
1002
2026-09-02
C02
1003
2026-09-03
C01
Every non-key field depends directly on order_id.
Remaining Tables in 3NF
Products
product_id (PK)
product_name
unit_price
P10
USB-C Hub
29.99
P20
Wireless Mouse
24.50
P30
Laptop Stand
39.00
Order_Items
order_id (PK, FK)
product_id (PK, FK)
quantity
1001
P10
1
1001
P20
2
1002
P10
1
1003
P30
1
1003
P20
1
Complete 3NF Schema
erDiagram
CUSTOMERS ||--o{ ORDERS : places
ORDERS ||--|{ ORDER_ITEMS : contains
PRODUCTS ||--o{ ORDER_ITEMS : appears_in
CUSTOMERS {
text customer_id PK
text customer_name
}
ORDERS {
int order_id PK
text order_date
text customer_id FK
}
PRODUCTS {
text product_id PK
text product_name
real unit_price
}
ORDER_ITEMS {
int order_id PK, FK
text product_id PK, FK
int quantity
}
Dataset Changes Across the Normal Forms
Stage
Structure
Main improvement
Unnormalized
One table with lists inside cells
Starting point
1NF
One flat table with one product per row
Atomic values
2NF
Orders, Products, and Order_Items
No partial dependencies
3NF
Customers, Orders, Products, and Order_Items
No transitive dependencies
The five order-item facts remain present at every stage.
Checking the 3NF Conversion
Check
Expected result
Unique customers in 1NF
2
Rows in Customers
2
Unique orders in 1NF
3
Rows in Orders
3
Unique products in 1NF
3
Rows in Products
3
Order-product rows in 1NF and Order_Items
5 in each
Matching counts help confirm that the split preserved every entity and relationship.
Benefits of the 3NF Design
Earlier problem
Improvement in 3NF
Ana’s name repeats on several rows
Customers stores it once
Product details repeat across orders
Products stores them once
Deleting an order could remove product details
Products remains independent
A product needs an order before it can be recorded
Products accepts it independently
Normalization Depends on Business Rules
The example assumes that:
Each product ID has one current price
One product appears at most once per order
Each order belongs to one customer
Different rules can require a different schema. For example, storing the sale price in Order_Items would preserve historical prices.
Activity: Normalize Student Enrollment Data
Unnormalized Dataset
student_id
student_name
email
major
courses
S101
Ana Rivera
ana@college.edu
M01, Data Science
C101, Databases, Dr. Kim, A; C202, Statistics, Dr. Patel, B+
S102
Jamal Lee
jamal@college.edu
M02, Computer Science
C101, Databases, Dr. Kim, B
S103
Mei Chen
mei@college.edu
M01, Data Science
C202, Statistics, Dr. Patel, A; C303, Programming, Dr. Gomez, A-
The major and courses columns contain multiple values. Therefore, the dataset does not satisfy first normal form.
Instructions
Part 1: Convert the Dataset to 1NF
Store only one value in each cell.
Create one row for each student-course combination.
Separate the values currently stored in the major and courses columns.
Use (student_id, course_id) as the composite primary key.