← thecodex.expert · The Codex Family of Knowledge

Free · No account · Official sources only

SQL — Cradle to Mastery

A complete, structured path through SQL — from your first SELECT to schema design, transactions, and query performance. Examples use PostgreSQL syntax throughout, with engine differences called out wherever they matter. Every lesson points at reference pages already written and verified on this site. Free, no account, no sign-up.

30 lessons 6 stages ~30 hours of reading Standard SQL, PostgreSQL syntax primarily · curriculum current as of 2026
Start Lesson 1 → Browse the reference instead

How this course works

1
Follow the stages in orderEach stage assumes the one before it. Stage 2 in particular assumes Stage 1 cold.
2
Read the tab the lesson namesReference pages have Beginner, Intermediate and Expert tabs. Read only what the lesson asks for on a first pass.
3
Run every queryKeep the playground open in a second tab. Reading a query you have not run is how misunderstandings survive in SQL more than almost any other language.
4
Design a real schema earlyDo not wait until Stage 2 ends to try designing something. Sketch a schema for a system you actually use as soon as keys and constraints make sense.
Casual pace: ~9 weeks at 4 hours a week
Steady pace: ~5 weeks at 8 hours a week
Intensive: ~2 weeks full-time
STAGE 0

Before You Start

SQL is not a general-purpose language, and it has no single official implementation. These two lessons explain what that means before you write a single query.

LESSON 1

What is SQL?

A 1970 IBM paper on relational theory, and the language built to make it usable

SQL traces back to a 1970 paper by Edgar Codd proposing the relational model, and to IBM's System R project that turned it into a working query language soon after. Unlike every other language in this course, SQL is declarative: you describe the result you want, not the steps to compute it, and the database engine decides how.

📚 🟩 Read the Beginner tab only.
Key focus: Why SQL describes *what* you want instead of *how* to get it, and what that changes about how you think.
⏱ 30 min
Required Reading
→
What is SQL? — The Codex

SQL's origin in relational theory, the declarative-vs-imperative distinction, and where SQL is used across the industry.

LESSON 2

Setting Up SQL

SQL has no interpreter of its own — pick an engine, then a client

There is no single “SQL runtime” to install the way there is a Python or Go compiler. You pick a database engine (this course uses PostgreSQL for examples) and a client to talk to it. This lesson gets a real database running locally so every later lesson can be typed and run, not just read.

📚 🟩 Read the Beginner tab only.
Key focus: Getting a real PostgreSQL database running locally, and a client connected to it.
⏱ 30 min
Required Reading
→
Setting Up SQL — The Codex

Installing PostgreSQL (or using a hosted/Docker instance), connecting with psql or a GUI client, and creating your first database.

STAGE 1

Querying Fundamentals

The core of daily SQL: asking for rows, narrowing them down, and ordering what comes back. Six lessons — everything here compounds into every query you will ever write.

LESSON 3

SELECT & FROM

The two words every SQL query starts with

Every query starts by naming which columns you want and which table they come from. This sounds trivial, but the exact order SQL evaluates a query in (FROM before SELECT, conceptually) explains several beginner surprises you will hit later, like why you cannot reference a computed column alias everywhere you might expect to.

📚 🟩 Read the Beginner tab only.
Key focus: The conceptual order a query is evaluated in, not just the order you type its clauses.
⏱ 45 min
Required Reading
→
SELECT & FROM — The Codex

SELECT and FROM syntax, column aliases, SELECT *, and a first look at the logical query-evaluation order.

LESSON 4

Filtering with WHERE

Comparisons, ranges, and pattern matching narrow down which rows come back

WHERE is the workhorse of nearly every query: it decides which rows survive before anything else happens to them. This lesson covers comparison operators, combining conditions with AND/OR, ranges with BETWEEN, and pattern matching with LIKE.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Building compound WHERE conditions correctly, including operator precedence between AND and OR.
⏱ 1 hours
Required Reading
→
Filtering with WHERE — The Codex

Comparison operators, AND/OR/NOT, BETWEEN, IN, LIKE pattern matching, and WHERE clause precedence.

LESSON 5

Sorting & Limiting

ORDER BY sets the sequence; LIMIT caps how many rows come back

Without ORDER BY, a database makes no promise about what order rows come back in at all — an easy beginner assumption to get wrong. LIMIT (and its engine-specific cousins) then caps the result to a manageable size, essential for pagination.

📚 🟩 Read the Beginner tab only.
Key focus: Why row order is undefined without ORDER BY, and how LIMIT syntax varies by engine.
⏱ 45 min
Required Reading
→
Sorting & Limiting — The Codex

ORDER BY on one or more columns, ASC/DESC, LIMIT and OFFSET, and the equivalent syntax in other engines like SQL Server's TOP.

LESSON 6

NULL Handling

NULL is not equal to anything — not zero, not empty string, not even another NULL

NULL represents the absence of a value, and SQL's three-valued logic (true, false, unknown) trips up nearly everyone once: `WHERE column = NULL` never matches anything, even a row where the column really is NULL. You need `IS NULL` instead.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Why `= NULL` silently matches nothing, and how COALESCE gives NULL a fallback value.
⏱ 45 min
Required Reading
→
NULL Handling — The Codex

Three-valued logic, IS NULL vs IS NOT NULL, NULL in comparisons and aggregates, and COALESCE.

LESSON 7

Data Types in SQL

Types vary more across engines than most languages' do

Unlike a programming language with one type system, SQL's types genuinely differ between PostgreSQL, MySQL, and SQLite — SQLite in particular uses “type affinity” rather than strict typing, which is the strangest case among the three. Knowing your engine's actual behavior matters here more than almost anywhere else in SQL.

📚 ⚡ Intermediate.
Key focus: Which type behaviors are portable across engines, and which (like SQLite's affinity system) are not.
⏱ 1 hours
Required Reading
→
Data Types in SQL — The Codex

Numeric, text, date/time and boolean types, engine-specific differences, and casting between types.

LESSON 8

Querying, Tied Together

SELECT, WHERE, ORDER BY, subqueries, and NULL handling in real, realistic queries

This lesson is the synthesis for this stage: seeing SELECT, WHERE, ORDER BY, CASE expressions, a first look at subqueries, and NULL-aware logic combined into the kind of query you would actually write against a real table, rather than each clause in isolation.

📚 ⚡ Intermediate.
Key focus: Combining everything in this stage into one realistic query, the way you actually will in practice.
⏱ 1 hours
Required Reading
→
Querying, Tied Together — The Codex

SELECT/WHERE/ORDER BY/LIMIT together, CASE expressions, a first look at subqueries, and string/date functions with PostgreSQL examples.

STAGE 2

Schema Design — SQL's Defining Discipline

This is the stage that makes SQL different from every other language in this course: before you can query good data, someone has to design a schema that keeps the data trustworthy. Five lessons on tables, keys, and the theory that keeps a schema from rotting.

LESSON 9

Creating Tables

CREATE TABLE defines your schema up front — ALTER TABLE changes it later, carefully

CREATE TABLE is where a schema becomes real: every column's name, type, and rules are declared before a single row exists. ALTER TABLE lets you change it afterward, but on a table with real data and real traffic, that has to be done carefully, not casually.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: The CREATE TABLE syntax, and why altering a live table is riskier than creating a new one.
⏱ 1 hours
Required Reading
→
Creating Tables — The Codex

CREATE TABLE syntax, column definitions, ALTER TABLE for adding/changing/dropping columns, and DROP TABLE.

LESSON 10

Constraints

NOT NULL, UNIQUE, CHECK, and DEFAULT — rules the database enforces on every row, always

A constraint is a rule the database itself enforces, rejecting any row that would break it, rather than trusting application code to always get validation right. This is one of SQL's biggest structural advantages over storing data as plain files or documents.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Why enforcing rules in the database beats trusting every application to validate correctly.
⏱ 45 min
Required Reading
→
Constraints — The Codex

NOT NULL, UNIQUE, CHECK, and DEFAULT constraints, and what happens when an INSERT violates one.

LESSON 11

Primary & Foreign Keys

A primary key identifies each row uniquely; a foreign key enforces a relationship actually exists

A primary key is a promise: this column (or combination of columns) is unique for every row, forever. A foreign key is a different promise: this value must exist as a primary key somewhere else, which is exactly what stops you from ever having an order that points at a customer who does not exist.

📚 ⚡ Intermediate.
Key focus: How a foreign key constraint physically prevents orphaned, relationship-breaking data.
⏱ 1 hours
Required Reading
→
Primary & Foreign Keys — The Codex

Primary keys (single and composite), foreign keys, referential integrity, and ON DELETE/ON UPDATE behavior.

LESSON 12

Normalization

Normal forms are a checklist for eliminating redundant, inconsistency-prone data

Normalization is a series of “normal forms,” each one eliminating a specific kind of redundancy that would otherwise let the same fact get stored in two places and quietly disagree with itself. You do not need to memorize the formal definitions to internalize the actual habit: each fact lives in exactly one place.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: The practical habit normalization teaches, more than the formal names of each normal form.
⏱ 1.25 hours
Required Reading
→
Normalization — The Codex

First, second, and third normal forms, what each one actually eliminates, and when denormalizing on purpose is the right call.

LESSON 13

Database Design

Putting normalization, keys, and indexing together into an actual schema

This lesson is the synthesis for this stage: taking normalization, primary/foreign keys, and a first look at indexing and actually designing a schema for a realistic small system, before any application code exists to use it.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Designing a real, multi-table schema from a plain-English description of what it needs to store.
⏱ 1.25 hours
Required Reading
→
Database Design — The Codex

Entity-relationship thinking, translating requirements into tables and relationships, and where indexing decisions belong in the design process.

STAGE 3

Joins, Aggregation & Advanced Queries

Real questions usually span more than one table, and often need a number computed across many rows rather than the rows themselves. Seven lessons on combining, grouping, and layering queries inside each other.

LESSON 14

Inner & Outer Joins

INNER JOIN keeps only matches; LEFT/RIGHT/FULL OUTER JOIN keep the unmatched rows too, as NULLs

An INNER JOIN only returns rows that match on both sides — which quietly drops data if that is not what you meant. An OUTER JOIN is how you deliberately keep the customers with zero orders, or the products that have never sold, showing NULLs for the side with no match.

📚 🟩 Beginner → ⚡ Intermediate → 🔥 Expert.
Key focus: Choosing INNER vs LEFT/RIGHT/FULL OUTER based on whether unmatched rows should disappear or stay.
⏱ 1.25 hours
Required Reading
→
Inner & Outer Joins — The Codex

INNER JOIN, LEFT/RIGHT/FULL OUTER JOIN, CROSS JOIN, self-joins, and how NULL shows up on the unmatched side.

LESSON 15

GROUP BY & HAVING

WHERE filters rows before grouping; HAVING filters groups after aggregation

GROUP BY collapses many rows into one per group, and aggregate functions like COUNT and SUM summarize each group. The classic confusion is WHERE vs HAVING: WHERE runs before grouping and cannot reference an aggregate, HAVING runs after and can.

📚 ⚡ Intermediate.
Key focus: Exactly why `WHERE COUNT(*) > 5` fails and `HAVING COUNT(*) > 5` is what you meant.
⏱ 1 hours
Required Reading
→
GROUP BY & HAVING — The Codex

GROUP BY on one or more columns, aggregate functions (COUNT, SUM, AVG, MIN, MAX), and the WHERE-vs-HAVING distinction.

LESSON 16

Subqueries

A query nested inside another — in WHERE, in FROM, or correlated to the outer row

A subquery is a complete SELECT living inside a larger query, and it comes in three flavors that behave quite differently: a scalar subquery in WHERE, a derived table in FROM, and a correlated subquery that re-runs once per outer row, which is easy to write by accident and expensive to run.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Recognizing a correlated subquery, and why it can be far slower than it looks.
⏱ 1.25 hours
Required Reading
→
Subqueries — The Codex

Scalar subqueries, subqueries in FROM (derived tables), correlated subqueries, and EXISTS vs IN.

LESSON 17

Common Table Expressions

WITH names a temporary result set for readability — and can even reference itself, recursively

A CTE, written with `WITH`, names a subquery so you can reference it by a readable name instead of nesting parentheses several layers deep. A recursive CTE goes further, referencing itself to walk a tree or graph structure, like an employee-to-manager hierarchy.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: When a CTE is purely for readability, and when a recursive CTE is the only practical way to write a query at all.
⏱ 1.25 hours
Required Reading
→
Common Table Expressions — The Codex

WITH syntax, chaining multiple CTEs, and recursive CTEs for hierarchical data.

LESSON 18

Window Functions

Computing across related rows without collapsing them into one, unlike GROUP BY

A window function computes something across a set of related rows — a running total, a rank, the previous row's value — without collapsing those rows into one, the way GROUP BY does. This is the feature that finally makes “rank each product within its category” a single clause instead of a self-join.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: The difference between a window function's OVER() and a GROUP BY: rows stay, they just gain a computed column.
⏱ 1.25 hours
Required Reading
→
Window Functions — The Codex

OVER() and PARTITION BY, ROW_NUMBER/RANK/DENSE_RANK, running totals, and LAG/LEAD for comparing adjacent rows.

LESSON 19

Set Operations

UNION, INTERSECT, and EXCEPT combine the results of two queries like set operations

These three operators treat query results the way you would treat mathematical sets: UNION combines them, INTERSECT keeps only what is in both, and EXCEPT keeps what is in the first but not the second. Each requires both queries to return the same number of compatible columns.

📚 ⚡ Intermediate.
Key focus: UNION vs UNION ALL, and why the column count and types must line up between both queries.
⏱ 45 min
Required Reading
→
Set Operations — The Codex

UNION and UNION ALL, INTERSECT, EXCEPT, and the column-compatibility rule they all share.

LESSON 20

Joins & Aggregates, Tied Together

Joins, GROUP BY, subqueries, and window functions in one realistic multi-table query

This lesson is the synthesis for this stage: combining joins across several tables with aggregation, a subquery, and a window function in the kind of query a real report or dashboard would actually need — seeing how the pieces you just learned individually compose in practice.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Writing one real, multi-table report query using everything in this stage together.
⏱ 1.25 hours
Required Reading
→
Joins & Aggregates, Tied Together — The Codex

JOINs (inner, left, right, full, cross, self-join) combined with GROUP BY, HAVING, and window functions in realistic queries.

STAGE 4

Transactions, Indexing & Performance

A database's real job is protecting data under concurrent, failure-prone conditions, and answering queries fast as a table grows to millions of rows. Five lessons most beginners skip and every production incident eventually forces you to learn anyway.

LESSON 21

Transactions

Several statements succeed or fail together, as one indivisible unit

A transaction groups multiple statements so that either all of them take effect or none do — transferring money between two accounts is the classic example, since a crash between the debit and the credit must not leave the money in neither account or both.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: Why BEGIN/COMMIT/ROLLBACK exists, using a case where a partial update would be actively dangerous.
⏱ 1 hours
Required Reading
→
Transactions — The Codex

BEGIN, COMMIT, ROLLBACK, savepoints, and what a transaction actually guarantees.

LESSON 22

ACID Properties

Atomicity, Consistency, Isolation, Durability — the four guarantees a real transaction makes

ACID names the four properties a transactional database promises: Atomicity (all-or-nothing), Consistency (never leaving the data in an invalid state), Isolation (concurrent transactions do not corrupt each other), and Durability (once committed, it survives a crash).

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: What each of the four letters actually guarantees, and what isolation levels trade off against each other.
⏱ 1 hours
Required Reading
→
ACID Properties — The Codex

Atomicity, Consistency, Isolation, Durability in detail, and an introduction to isolation levels and the anomalies they prevent.

LESSON 23

Indexing

An index speeds up reads and slows down writes — there is no free lunch, only a tradeoff

An index lets the database find matching rows without scanning the whole table, the same way a book's index beats reading every page. But every index also has to be updated on every INSERT/UPDATE/DELETE, so adding indexes freely is a real tradeoff, not a pure win.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Recognizing when an index will actually help a slow query, versus when it just slows down writes for nothing.
⏱ 1.25 hours
Required Reading
→
Indexing — The Codex

B-tree indexes, when a column is worth indexing, composite indexes, and the write-cost tradeoff.

LESSON 24

Execution Plans

EXPLAIN shows exactly how the engine intends to run your query

EXPLAIN (and EXPLAIN ANALYZE) shows you the actual plan the database chose: which indexes it used, in what order it joined tables, and how many rows it expects at each step. Reading one is how you stop guessing why a query is slow and start knowing.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Reading an EXPLAIN plan well enough to spot a full table scan where an index scan was expected.
⏱ 1.25 hours
Required Reading
→
Execution Plans — The Codex

EXPLAIN vs EXPLAIN ANALYZE, sequential scans vs index scans, join strategies, and reading estimated vs actual row counts.

LESSON 25

Query Optimization

A handful of habits separate a query that scales from one that quietly gets slower every month

Most real-world slow queries share a small set of causes: a missing index, a function applied to a column that blocks index use, a correlated subquery that should have been a join, or a SELECT * pulling far more than is needed. This lesson is a checklist built from those recurring causes.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: A practical checklist for the handful of mistakes that account for most slow queries in practice.
⏱ 1 hours
Required Reading
→
Query Optimization — The Codex

Common performance pitfalls, rewriting a correlated subquery as a join, avoiding functions on indexed columns, and SELECT * in production code.

STAGE 5

Beyond Basic Queries

Views, stored logic, security, and the DDL/transaction/EXPLAIN material advanced-sql ties together. Five lessons that round out what a working database professional actually uses day to day.

LESSON 26

Views

A saved query that looks like a table — no data is duplicated, unless you materialize it

A view wraps a query behind a name you can SELECT from like a table, which is useful for hiding complexity or restricting which columns a user can see. A regular view re-runs its query every time; a materialized view caches the result and has to be refreshed on purpose.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: The difference between a plain view (always live) and a materialized view (a cached snapshot).
⏱ 45 min
Required Reading
→
Views — The Codex

CREATE VIEW, querying through a view, updatable views, and materialized views.

LESSON 27

Stored Procedures

Reusable logic stored inside the database itself — syntax varies wildly between engines

A stored procedure keeps logic next to the data it operates on, callable from any client without duplicating the logic in every application. This is also the topic where engines diverge the most — PostgreSQL's PL/pgSQL, MySQL's syntax, and SQL Server's T-SQL are not interchangeable.

📚 ⚡ Intermediate.
Key focus: Why stored procedure syntax is one of the least portable parts of SQL across engines.
⏱ 1 hours
Required Reading
→
Stored Procedures — The Codex

CREATE PROCEDURE/FUNCTION basics, parameters, and the major engine-specific dialects.

LESSON 28

Triggers

Runs automatically on insert/update/delete — powerful, and easy to hide bugs inside

A trigger fires automatically in response to a data change, useful for enforcing rules an ordinary constraint cannot express or for keeping an audit log. The risk is real too: logic hidden inside a trigger is easy to forget exists, and can surprise anyone debugging unexpected side effects later.

📚 ⚡ Intermediate → 🔥 Expert.
Key focus: Weighing a trigger's power against the debugging cost of logic that runs invisibly.
⏱ 1 hours
Required Reading
→
Triggers — The Codex

CREATE TRIGGER, BEFORE/AFTER and row/statement-level triggers, and when a trigger is the wrong tool.

LESSON 29

SQL Injection & Security

Parameterized queries are the fix — not sanitizing input, not escaping quotes

SQL injection happens when untrusted input gets concatenated directly into a query string, letting an attacker change what the query actually does. The fix is not more careful string escaping — it is never building a query by concatenation in the first place: parameterized queries separate code from data entirely.

📚 🟩 Beginner → ⚡ Intermediate.
Key focus: A real vulnerable-query example, and why parameterization fixes it structurally, not just cosmetically.
⏱ 1 hours
Required Reading
→
SQL Injection & Security — The Codex

A concrete SQL injection example, why escaping quotes is not a real fix, and parameterized queries / prepared statements as the actual solution.

LESSON 30

Advanced SQL, Tied Together

CTEs, DDL, transactions, ACID, EXPLAIN ANALYZE, and JSONB in combination

This lesson is the course's final synthesis: recursive CTEs, schema changes with ALTER, a transaction wrapping several statements, reading its EXPLAIN ANALYZE output, and a look at PostgreSQL's JSONB type for when a column needs to hold semi-structured data — the advanced end of everything this course has covered, working together.

📚 🔥 Expert.
Key focus: Seeing advanced features from every earlier stage combined in realistic, production-shaped SQL.
⏱ 1.5 hours
Required Reading
→
Advanced SQL, Tied Together — The Codex

CTEs and recursive queries, DDL (CREATE TABLE, ALTER, indexes, views) in combination, transactions and ACID in practice, EXPLAIN ANALYZE, and PostgreSQL's JSONB type.

STAGE 6

Concepts That Cross Languages

SQL is declarative, not imperative, so it shares fewer of these cross-language ideas than a general-purpose language does — there is no SQL equivalent of a loop or a user-defined function in ordinary querying. The handful below genuinely apply and are worth reading once.

Concept Pages
STAGE 7

Build Real Things

Every other language on this site pairs its course with the same 10-project set (a number-guessing game, a REST API, and so on). SQL genuinely does not fit that set — there is no idiomatic “chat server” or “compiler” written in pure SQL. SQL’s own project set needs to be SQL-shaped instead: schema-design exercises, query challenges against a real dataset, and the kind of performance-tuning problem EXPLAIN was built for. That set has not been designed yet, so nothing is linked here that does not exist. The most useful thing to do with what you have learned so far is practice directly in the playground below against real tables, and this section will be filled in with SQL-appropriate projects in a future update.

STAGE 8

Practice & Experimentation

Ongoing, not a final step. Run every query you read against a real table rather than just reading it — SQL rewards typing things out far more than most languages do.

Resources
→
SQL Playground

Run real SQL queries against sample data without installing anything.

→
SQL Snippets

Copy-ready idiomatic queries to keep beside you while you write your own.

→
SQL Reference Hub

All 30 topic pages in one index, for looking things up later.