Part 0 · 5 chapters · ~20 min

Where SQL came from

This module is not a SQL tutorial. You have written SQL for years. It is SQL as a formal system — what each clause means, in what order the engine evaluates it, and why your intuition about NULL is wrong. That starts with knowing which parts of the language are principled and which are historical accidents, because the two need very different treatment.

1

Codd’s 1970 paper

Edgar F. Codd, an IBM researcher, published A Relational Model of Data for Large Shared Data Banks in 1970. The problem he was solving is easy to underestimate now, because we have forgotten the alternative.

Databases of the era — IMS, CODASYL — required you to navigate. To find a customer's orders you followed pointers through a hierarchy or network, in code, in the order the database had physically stored them. Your program encoded the physical layout. Change the layout and every program broke.

Codd's proposal was physical data independence: describe data as mathematical relations, query it by describing what you want, and let the system decide how to retrieve it. The schema and the access path become separate concerns.

why this still matters to you
Every time the optimizer picks an index you did not name, that is Codd's promise being kept. And every time you fight the optimizer with a hint, you are partially withdrawing from the bargain — which is the real reason hints should be temporary (MySQL module, ch 87).

The model rests on three ideas: data is held in relations (sets of tuples over named, typed attributes), manipulated by a closed algebra (operations on relations return relations, so they compose), and accessed by value, never by position or pointer.

2

SEQUEL, System R, and why the syntax looks like English

Codd's own query language, Alpha, was mathematical. In 1974 Donald Chamberlin and Raymond Boyce at IBM designed SEQUEL — Structured English Query Language — deliberately targeting users who were not mathematicians. The English-like syntax was a product decision about adoption.

It was renamed SQL because SEQUEL was a trademark of a British aircraft company. The pronunciation argument descends directly from that, and both are correct.

SEQUEL was implemented in System R, IBM's prototype, which contributed far more than a language. System R produced the first cost-based optimizer, the ARIES-lineage recovery ideas, and the isolation-level definitions still in use. Much of the MySQL module describes System R's intellectual descendants.

the design tension you live with daily
SQL's English-like surface makes simple queries readable and complex ones misleading. SELECT ... FROM ... WHERE reads in an order that is not the order of evaluation — which is precisely why chapter 6 exists and why so many people are confused about aliases, HAVING and window functions. The friendliness has a permanent cost.
3

The standards, 1986 to 2023

Know which release introduced what, because it tells you what you can rely on across engines.

1986
SQL-86First ANSI standard. Ratifies what vendors already shipped.
1992
SQL-92The big one. Explicit JOIN syntax, CASE, subqueries in FROM, the isolation levels you still quote. "SQL-92 compliant" was the marketing line for a decade.
1999
SQL:1999Recursive CTEs, triggers, user-defined types, booleans, GROUPING SETS. Recursion made SQL Turing-complete.
2003
SQL:2003Window functions, MERGE, sequences, XML. Most of Part 4 of this module dates from here.
2008 / 2011
SQL:2008, SQL:2011TRUNCATE, FETCH FIRST; then temporal tables and system versioning.
2016
SQL:2016JSON support, JSON_TABLE, row pattern recognition (MATCH_RECOGNIZE), polymorphic table functions.
2023
SQL:2023Property graph queries (SQL/PGQ), a proper JSON type, ANY_VALUE. Implementations are early.
standards describe, they do not compel
No engine implements the whole standard, and the standard is not freely available — ISO sells it. That combination means the de facto standard is "what Postgres, MySQL, SQL Server and Oracle all happen to support", which you discover empirically. Anything from SQL-92 is genuinely portable; anything after needs checking.
4

Why every dialect diverges

Four forces, all of them structural rather than careless:

  1. Vendors shipped before the standard existed. Oracle had DECODE and ROWNUM before CASE and LIMIT were standardized. Backward compatibility then froze them.
  2. The standard leaves things implementation-defined. NULL sort order, identifier case sensitivity, and the exact behaviour of several functions are explicitly left open.
  3. Engine architecture leaks through. MySQL has no merge join because InnoDB's storage model makes it less useful; Postgres has index access methods because it was designed for extensibility. The SQL you can write efficiently follows the engine beneath it.
  4. Extensions are competitive advantage. JSONB, ON CONFLICT, SKIP LOCKED, arrays — vendors ship them to win, and the standard catches up later, sometimes with different syntax.
TaskMySQLPostgreSQLStandard
Limit rowsLIMIT nLIMIT nFETCH FIRST n ROWS ONLY
UpsertON DUPLICATE KEY UPDATEON CONFLICT DO UPDATEMERGE
String concatCONCAT(a,b)a || ba || b
Return modified rows— (use LAST_INSERT_ID())RETURNINGRETURNING (2023)
Conditional aggregateSUM(x = 1)COUNT(*) FILTER (WHERE …)FILTER
Quote an identifier`col`"col""col"
this module’s convention
Examples are written in whichever dialect shows the concept most clearly, always labelled, with the portable form given where it differs meaningfully. Chasing perfect portability obscures the ideas, and in practice nobody writes fully portable SQL anyway.
5

Where SQL betrays the relational model

SQL is based on the relational model but departs from it in four ways that cause real confusion. Naming them explicitly is the best preparation for Part 1.

Relational modelSQLWhat it costs you
A relation is a set — no duplicatesA table is a bag — duplicates allowedUNION deduplicates, UNION ALL does not, and they have wildly different costs. Chapter 11.
Attributes are unorderedColumns have positions; SELECT * and ORDER BY 1 depend on themAdding a column can silently change a query's meaning. Chapter 76.
Every value is presentNULL, and three-valued logicThe single largest source of SQL bugs. Chapters 8–10.
Rows are unorderedResult sets are ordered by ORDER BY, undefined without itA query that "always returns them in order" until the plan changes.

Codd's own objection

Codd disliked SQL, particularly NULL as implemented. His position was that a missing value and an inapplicable value are different things needing different markers. SQL collapses both into one NULL, which is why NULL = NULL is unknown rather than either true or false.

the framing to carry through this module
When SQL behaves surprisingly, ask which of these four departures is responsible. Almost every classic gotcha — the NOT IN trap, duplicate rows after a join, aggregates that ignore NULLs, a result order that changes after an upgrade — traces back to exactly one of them.
run it
-- 1. bags, not sets
SELECT 1 UNION ALL SELECT 1;    -- two rows. not a set.
SELECT 1 UNION     SELECT 1;    -- one row. dedup costs a sort or hash.

-- 2. columns have positions
SELECT 2 AS a, 1 AS b ORDER BY 1;   -- orders by 'a' — by POSITION

-- 3. NULL and three-valued logic
SELECT NULL = NULL;              -- NULL, not 1
SELECT NULL <> NULL;             -- NULL, not 0
SELECT NULL IS NULL;             -- 1. the only test that works.

-- 4. row order is undefined without ORDER BY
--    this may LOOK ordered for years, then change with a new
--    index or a plan change. never rely on it.
SELECT id FROM some_table LIMIT 10;

Part 1 takes the third and fourth of those seriously — evaluation order and NULL — because together they explain most of the behaviour that surprises experienced engineers.