DOCODIVE
Beginner Free Learning Path

Databases Beginner Course

Learn how the world stores its data. Master SQL, CRUD, joins, normalization, keys, indexes, transactions, Python database access, and build a library database capstone.

4–6 weeks 20 lessons 1 capstone Basic Python required
Start Learning
01

What Is a Database?

14 min
What you'll learn
  • Define database
  • Understand DBMS
  • Know why databases beat files

A database is an organized collection of data managed by a DBMS (Database Management System). Unlike flat files, databases guarantee data integrity, concurrent access, fast queries, and durability. Every app you use — banking, social media, e-commerce — stores its data in a database. Understanding databases means understanding where and how the world's information lives.

intro.py
# File (fragile) vs Database (structured)
# File: no constraints, no concurrency, slow search
# Database: schema, ACID, indexes, multi-user
print('Databases organize, protect, and query data')
Output
sql
Databases organize, protect, and query data
🔎 Important: Databases exist for four reasons: integrity, concurrency, speed, and durability. Files give you none.
Try it yourself

Name three real apps that use databases.

Think data-heavy apps.
Banking, social media, e-commerce, healthcare, gaming.
02

Relational vs NoSQL Databases

16 min
What you'll learn
  • Distinguish SQL and NoSQL
  • Know when to use each
  • Understand data models

Relational databases (MySQL, PostgreSQL) store data in tables with rigid schemas and relationships — perfect for structured, transactional data. NoSQL databases (MongoDB, Redis) store documents, key-values, or graphs — flexible, horizontally scalable, ideal for unstructured or rapidly-changing data. The choice is a design decision: consistency and relationships (SQL) vs flexibility and scale (NoSQL).

comparison.py
# Relational: tables, rows, joins
# NoSQL: documents, key-value, graphs
comparison = {
    'SQL': 'structured, ACID, joins, vertical scaling',
    'NoSQL': 'flexible, horizontal scaling, eventual consistency'
}
print(comparison)
Live Preview
Relational vs NoSQL Databases
SQL
NoSQL
💡 Tip: If your data has clear relationships and needs strict consistency, pick SQL. If it's unstructured and needs scale, pick NoSQL.
Try it yourself

Which is better for a social feed with millions of users?

Scale.
NoSQL — horizontal scaling for massive unstructured data.
03

Tables, Rows & Columns

14 min
What you'll learn
  • Understand relational structure
  • Learn rows vs columns
  • Grasp primary keys

A relational database is made of tables — each table has columns (fields) and rows (records). A users table has columns like id, name, email; each user is a row. The PRIMARY KEY uniquely identifies each row. This tabular structure is the foundation of all SQL. Everything else — queries, joins, indexes — operates on this simple grid.

table.sql
CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    email TEXT UNIQUE,
    age INTEGER
);
Live Preview
Tables, Rows & Columns
id
name
email
🔎 Important: Primary key = unique identifier. Every table needs one — it's how you refer to a specific row.
Try it yourself

What column type would you use for a primary key?

Unique + auto-increment.
An auto-incrementing integer.
04

SQL Basics: SELECT & WHERE

18 min
What you'll learn
  • Write SELECT queries
  • Filter with WHERE
  • Understand the query flow

SELECT is the most important SQL command — it retrieves data. SELECT column FROM table fetches values; WHERE filters rows by condition. The query flow: FROM (pick table) → WHERE (filter rows) → SELECT (pick columns). Master SELECT + WHERE and you can answer most basic data questions. It's the 'print' of databases.

select.sql
-- Get names of users over 18
SELECT name, email
FROM users
WHERE age > 18;
Live Preview
SQL Basics: SELECT & WHERE
id
name
email
✓ Best Practice: Filter with WHERE BEFORE selecting — databases apply WHERE first, then SELECT. Get used to this order.
Try it yourself

Write a query to select all columns from a products table.

Use *.
SELECT * FROM products;
05

SQL Basics: INSERT, UPDATE, DELETE

18 min
What you'll learn
  • Add, modify, remove rows
  • Use parameterized queries
  • Understand CRUD

CRUD — Create, Read, Update, Delete — is the full data lifecycle. INSERT adds rows; SELECT reads; UPDATE modifies; DELETE removes. Together they're the four operations every app performs on data. The critical safety rule: always use a WHERE clause with UPDATE and DELETE — without it, you modify or delete EVERY row.

crud.sql
-- CREATE
INSERT INTO users (name, email) VALUES ('Ali', '[email protected]');
-- UPDATE
UPDATE users SET age = 22 WHERE name = 'Ali';
-- DELETE
DELETE FROM users WHERE age < 18;
Live Preview
SQL Basics: INSERT, UPDATE, DELETE
CREATE
READ
UPDATE
DELETE
⚠️ Common Mistake: UPDATE/DELETE WITHOUT WHERE = you just changed or deleted EVERYTHING. Always filter.
Try it yourself

Why is WHERE critical in DELETE?

Prevent disaster.
Without WHERE, DELETE removes all rows — catastrophic data loss.
06

SQL Aggregate Functions

16 min
What you'll learn
  • Use COUNT, SUM, AVG, MIN, MAX
  • Group with GROUP BY
  • Summarize data

Aggregate functions collapse many rows into one summary value. COUNT counts rows, SUM totals a column, AVG averages, MIN/MAX find extremes. GROUP BY groups rows by a column before aggregating — total sales per region, average age per department. This turns raw data into insights: one line of SQL replaces loops of Python code.

aggregate.sql
SELECT department, COUNT(*) AS employee_count, AVG(salary) AS avg_salary
FROM employees
GROUP BY department;
Live Preview
SQL Aggregate Functions
18
COUNT
78000
AVG
MAX
120000
✓ Best Practice: GROUP BY + aggregates is the heart of data analysis — let the database summarize, don't loop in Python.
Try it yourself

How do you count all rows in a table?

COUNT(*).
SELECT COUNT(*) FROM table_name;
07

SQL Joins

22 min
What you'll learn
  • Combine tables with JOIN
  • Learn INNER/LEFT/RIGHT joins
  • Resolve relationships

Joins combine rows from multiple tables based on a related column — the power that makes relational databases relational. INNER JOIN keeps only matching rows; LEFT JOIN keeps all left rows plus matches; RIGHT JOIN the opposite. Example: join orders with customers to show who ordered what. Joins connect the dots across your schema.

join.sql
SELECT users.name, orders.total
FROM users
INNER JOIN orders ON users.id = orders.user_id;
Live Preview
SQL Joins
users
⋈
orders
=
joined
🔎 Important: JOIN ON is the syntax — ON specifies WHICH columns relate the two tables.
Try it yourself

Which join keeps ALL rows from the left table?

LEFT.
LEFT JOIN.
08

Database Normalization

24 min
What you'll learn
  • Understand normalization
  • Learn 1NF, 2NF, 3NF
  • Eliminate redundancy

Normalization organizes data to eliminate redundancy and prevent anomalies — the same data stored once, referenced everywhere. 1NF: atomic values, no repeating groups. 2NF: no partial dependencies. 3NF: no transitive dependencies. The goal: every fact stored exactly once. Normalized schemas are cleaner, consistent, and the standard for transactional systems.

normalization.sql
# Unnormalized: orders has customer_name repeated
# Normalized: customers table + orders references customer_id
-- customers: (id, name, email)
-- orders: (id, customer_id, total)  ← no name duplication
Live Preview
Database Normalization
customers (id, name, email)
orders (id, customer_id, total)

No duplication — customer referenced by id

✓ Best Practice: Normalization rule of thumb: every piece of data stored exactly ONCE. Duplication = future inconsistency.
Try it yourself

What's the main goal of normalization?

Redundancy.
Eliminate data redundancy and anomalies.
09

Primary & Foreign Keys

18 min
What you'll learn
  • Define primary and foreign keys
  • Enforce referential integrity
  • Build relationships

A primary key uniquely identifies a row in its table. A foreign key in another table references that primary key, creating a relationship and enforcing referential integrity — you can't have an order for a non-existent customer. This constraint is the backbone of relational design: related data stays consistent automatically, because the database rejects orphaned references.

keys.sql
CREATE TABLE customers (
    id INTEGER PRIMARY KEY,
    name TEXT
);
CREATE TABLE orders (
    id INTEGER PRIMARY KEY,
    customer_id INTEGER,
    FOREIGN KEY (customer_id) REFERENCES customers(id)
);
Live Preview
Primary & Foreign Keys
PK: id
→
FK: customer_id
🔎 Important: Foreign keys are constraints, not just convention — the database itself enforces relationship integrity.
Try it yourself

What does referential integrity prevent?

Orphan rows.
Rows referencing non-existent parent rows.
10

Indexes & Query Performance

22 min
What you'll learn
  • Understand why indexes speed queries
  • Create indexes
  • Know the trade-off

Indexes are like a book's index — they let the database find rows without scanning the entire table. An index on a column enables O(log n) lookups instead of O(n) scans. The trade-off: indexes speed SELECT but slow INSERT/UPDATE/DELETE (must maintain the index), and consume storage. Index the columns you search and join on — not everything.

index.sql
CREATE INDEX idx_users_email ON users(email);

-- This query now uses the index
SELECT * FROM users WHERE email = '[email protected]';
Live Preview
Indexes & Query Performance
email index
=
O(log n) lookup
✓ Best Practice: Index columns you filter (WHERE) and join (ON) on. Don't over-index — writes get slower.
Try it yourself

Index's main downside?

Writes.
Slower writes — INSERT/UPDATE must maintain the index.
11

Transactions & ACID

22 min
What you'll learn
  • Understand transactions
  • Learn ACID properties
  • Guarantee data safety

A transaction is a group of operations that succeed or fail TOGETHER — like transferring money (deduct from A, add to B: both or neither). ACID guarantees: Atomicity (all or nothing), Consistency (valid state), Isolation (concurrent transactions don't interfere), Durability (committed data survives crashes). Transactions are why banks don't lose money to race conditions.

transaction.sql
BEGIN TRANSACTION;
UPDATE accounts SET balance = balance - 100 WHERE id = 1;
UPDATE accounts SET balance = balance + 100 WHERE id = 2;
COMMIT;  -- both applied, or ROLLBACK undoes both
Live Preview
Transactions & ACID
A
C
I
D
🔎 Important: ACID is the promise that makes databases trustworthy — without it, banking would be impossible.
Try it yourself

What does Atomicity mean?

All or nothing.
A transaction either fully completes or fully rolls back — no partial state.
12

SQL Views

16 min
What you'll learn
  • Create virtual tables
  • Simplify complex queries
  • Add a security layer

A view is a saved SELECT query that acts like a virtual table. It simplifies complex joins, encapsulates business logic, and can hide sensitive columns. Instead of writing a 10-line join every time, you create a view once and SELECT from it. Views are queries stored in the database — the ultimate DRY (Don't Repeat Yourself) tool for SQL.

view.sql
CREATE VIEW active_users AS
SELECT id, name, email
FROM users
WHERE is_active = 1;

SELECT * FROM active_users;
Live Preview
SQL Views
View
=
saved query
💡 Tip: Views wrap complex queries — name the query once, reuse it everywhere like a function.
Try it yourself

A view is like what in programming?

Reusable.
A function — saved logic you can call repeatedly.
13

Python + SQLite

22 min
What you'll learn
  • Connect Python to a database
  • Execute SQL from Python
  • Use parameterized queries

SQLite is a file-based database built into Python — zero setup, perfect for learning and small apps. The sqlite3 module connects Python and SQL: create a connection, get a cursor, execute SQL, commit, close. Parameterized queries (?) prevent SQL injection — never string-format user input into SQL. This is how apps talk to databases.

sqlite.py
import sqlite3

conn = sqlite3.connect('app.db')
cursor = conn.cursor()
cursor.execute('CREATE TABLE users (id INTEGER PRIMARY KEY, name TEXT)')
cursor.execute('INSERT INTO users (name) VALUES (?)', ('Ali',))
conn.commit()
cursor.execute('SELECT * FROM users')
print(cursor.fetchall())
conn.close()
Live Preview
Python + SQLite
🗄️ → 🐍
⚠️ Common Mistake: ALWAYS use ? placeholders for user input — string-formatting SQL is how SQL injection happens.
Try it yourself

Why use ? placeholders?

Injection.
To prevent SQL injection by safely escaping user input.
14

SQL Injection & Security

22 min
What you'll learn
  • Understand SQL injection
  • Prevent attacks
  • Write secure queries

SQL injection is the #1 database vulnerability: attacker input like '; DROP TABLE users; --' gets executed as SQL when you concatenate strings. Prevention: parameterized queries (placeholders), ORMs, input validation, and least-privilege database accounts. Understanding this attack is essential — it's how millions of records get leaked every year.

security.py
# VULNERABLE (never do this)
# query = f"SELECT * FROM users WHERE name = '{user_input}'"

# SAFE
cursor.execute('SELECT * FROM users WHERE name = ?', (user_input,))
Live Preview
SQL Injection & Security
⚠ injection
→
? placeholders
⚠️ Common Mistake: Every SQL injection in history could've been prevented with parameterized queries. Never concatenate user input into SQL.
Try it yourself

What's the #1 defense against SQL injection?

Placeholders.
Parameterized queries (prepared statements).
15

Object-Relational Mapping (ORM)

20 min
What you'll learn
  • Understand ORMs
  • Use SQLAlchemy
  • Map Python classes to tables

An ORM (Object-Relational Mapping) lets you work with databases using Python objects instead of raw SQL — a User class maps to a users table, attributes to columns. SQLAlchemy is Python's standard ORM. Benefits: type safety, cleaner code, database-agnostic (switch DBs without rewriting). Trade-off: some performance loss and hidden complexity. ORMs power most web frameworks.

orm.py
from sqlalchemy import Column, Integer, String, create_engine
from sqlalchemy.orm import declarative_base

Base = declarative_base()
class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)
    email = Column(String)
Live Preview
Object-Relational Mapping (ORM)
class User
⇄
users table
✓ Best Practice: ORMs trade a little raw speed for massive developer productivity — the default in web frameworks.
Try it yourself

What does an ORM map?

Objects to tables.
Python classes/objects to database tables/rows.
16

Database Backup & Recovery

18 min
What you'll learn
  • Understand backup strategies
  • Learn restore procedures
  • Protect against data loss

Backups are your last line of defense — full backups (everything), incremental (changes since last backup), and continuous (transaction logs). The 3-2-1 rule: 3 copies, 2 media types, 1 offsite. Recovery means restoring to a point in time. No backup = data loss is permanent. This is operational database skill every developer needs.

backup.py
# PostgreSQL backup
# pg_dump mydb > backup.sql
# restore
# psql mydb < backup.sql

# SQLite backup
import sqlite3
src = sqlite3.connect('app.db'); dst = sqlite3.connect('backup.db')
src.backup(dst)
Live Preview
Database Backup & Recovery
app.db
→
backup.db
🔎 Important: Test your restores — a backup you can't restore is worthless. The 3-2-1 rule is the professional standard.
Try it yourself

What's the 3-2-1 backup rule?

Copies, media, offsite.
3 copies, 2 media types, 1 offsite.
17

Database Design Basics (ERD)

20 min
What you'll learn
  • Design entity-relationship diagrams
  • Identify entities and relations
  • Translate ERDs to tables

An Entity-Relationship Diagram (ERD) visualizes your data model: entities (tables), attributes (columns), and relationships (one-to-one, one-to-many, many-to-many). Before writing CREATE TABLE, you sketch the ERD. One-to-many (customer→orders) is the most common; many-to-many needs a junction table. Good design upfront prevents painful migrations later.

design.sql
# Entities: Customer (1) --- (many) Orders
# Many-to-many: Students <-> Courses needs enrollment table
customers(id, name)
orders(id, customer_id, total)
enrollments(student_id, course_id)
Live Preview
Database Design Basics (ERD)
Customer
1—many
Orders
💡 Tip: Design the ERD BEFORE writing schema — it catches relationship mistakes early, when changes are cheap.
Try it yourself

How do you model many-to-many in relational DB?

Junction table.
A junction table with two foreign keys.
18

Constraints & Data Integrity

18 min
What you'll learn
  • Use constraints
  • Enforce valid data
  • Prevent bad records

Constraints are rules the database enforces: NOT NULL (required), UNIQUE (no duplicates), CHECK (value range), DEFAULT (fallback), FOREIGN KEY (relationship). They make the database self-protecting — invalid data can't even enter. Better to reject bad data at write time than clean it up later. Constraints are your schema's immune system.

constraints.sql
CREATE TABLE products (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    price DECIMAL CHECK (price >= 0),
    stock INTEGER DEFAULT 0,
    UNIQUE(name)
);
Live Preview
Constraints & Data Integrity
NOT NULL
UNIQUE
CHECK
✓ Best Practice: Push validation INTO the database with constraints — the DB becomes the last line of defense against bad data.
Try it yourself

Which constraint ensures a column can't be empty?

Required.
NOT NULL.
19

Intro to PostgreSQL vs MySQL

20 min
What you'll learn
  • Compare popular databases
  • Know feature differences
  • Choose the right DB

PostgreSQL and MySQL are the two dominant open-source relational databases. PostgreSQL: feature-rich, standards-compliant, advanced types (JSON, arrays), the choice for complex applications. MySQL: fast, simple, widely used in web apps (WordPress), great for read-heavy workloads. Both are excellent — the choice depends on complexity and ecosystem. PostgreSQL is the modern default for new projects.

compare.sql
# PostgreSQL strengths: JSONB, full-text, complex queries, extensions
# MySQL strengths: simplicity, replication, huge hosting ecosystem
print('PostgreSQL = features; MySQL = simplicity + hosting')
Live Preview
Intro to PostgreSQL vs MySQL
PostgreSQL
MySQL
💡 Tip: New project, complex data → PostgreSQL. Simple web app with huge hosting options → MySQL. Both are great.
Try it yourself

Which DB is known for advanced JSON support?

JSONB.
PostgreSQL.
20

Capstone: Build a Library Database

50 min
What you'll learn
  • Design a complete schema
  • Apply CRUD, joins, constraints
  • Query real relationships

Your capstone: build a library database. Design tables (books, authors, borrowers, loans), define relationships, add constraints, then write queries — find books by author, active loans, overdue books. This applies everything: schema design, keys, joins, aggregates, constraints. It's the complete, portfolio-ready database project.

capstone.sql
CREATE TABLE authors (id INTEGER PRIMARY KEY, name TEXT);
CREATE TABLE books (id INTEGER PRIMARY KEY, title TEXT, author_id INTEGER,
    FOREIGN KEY (author_id) REFERENCES authors(id));
CREATE TABLE loans (id INTEGER PRIMARY KEY, book_id INTEGER,
    due_date DATE,
    FOREIGN KEY (book_id) REFERENCES books(id));

-- Query: books by author
SELECT books.title FROM books
JOIN authors ON books.author_id = authors.id
WHERE authors.name = 'JK Rowling';
Live Preview
Capstone: Build a Library Database
authors (id, name)
books (id, title, author_id)
loans (id, book_id, due_date)
✓ Best Practice: This capstone = schema design + keys + joins + constraints — the full database skill set in one project.
Try it yourself

What query finds all overdue loans?

Date comparison.
SELECT * FROM loans WHERE due_date < CURRENT_DATE;
You've completed all 20 lessons. Ready for more?

Continue to Databases Intermediate for advanced SQL, query optimization, and NoSQL.

📱 Scan this QR code with your phone camera to instantly open this page.

Works on iOS, Android, and any modern device. No app installation required.

✅

Account Verified!

Your email has been verified successfully.