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.