# Outgrowing the Sheet: SQL & Databases

You hit one of the walls from Phase 1 - the file got slow, the IDs got mangled, or three "final"
versions disagreed. That's not a failure. It's the signal that your data has grown up and needs a home
built for the job. That home is a **database**, and the language you use to talk to it is **SQL**.

Here's the reassuring part: a database isn't a strange new world, it's a spreadsheet's ideas made
sturdy. If you understand a sheet, you're most of the way to understanding a table.

## The mental model: a table is a sheet that keeps its promises

📝 **Terminology.** A **database** is an organized store of data, managed by software built to keep it
correct and fast. A **table** is one collection of data inside it - rows and columns, like a single
spreadsheet tab. **SQL** (Structured Query Language) is how you ask the database to fetch, filter, or
change data.

The shapes map almost one-to-one:

```text
   SPREADSHEET                          DATABASE
   ───────────                          ────────
   a sheet/tab          →               a table
   a row                →               a row  (one record: one order, one user)
   a column             →               a column  (but with a DECLARED type)
   a cell               →               a value
   a formula / VLOOKUP  →               a SQL query (asked of the whole table)
```

*What just happened:* The pieces are the same. The difference is everything around them. A table
*declares* what each column holds and refuses anything that doesn't fit, the database is one shared store
instead of a file you copy, and SQL lets you ask questions across millions of rows without dragging a
formula anywhere. Each of those maps to a Phase 1 pain.

## One shared source of truth

In Phase 1, files multiplied until nobody knew which number was real. A database fixes this at the root:
there is *one* table, living in one place, and everyone connects to that same table. There's no copy in
someone's Downloads folder, because there are no copies - only connections.

```text
   Spreadsheet world:                  Database world:

   you ── budget_v2.xlsx                you ─┐
   me  ── budget_FINAL.xlsx            me  ─┼─→  ONE orders table
   her ── budget_USE_THIS.xlsx         her ─┘    (everyone sees the same rows)
```

*What just happened:* The "which version is current?" question disappears, because there's only ever one
version. Read the `orders` table and you're reading the live, current data - the same data your teammate
sees at the same moment. Next time two reports disagree, there's no afternoon spent hunting for the
"right" file - there's one table, and the answer is whatever it says right now.

## Real types and constraints

In Phase 1, a "date" column was a mix of real dates and look-alike text, and IDs got auto-mangled. A
database makes you *declare* each column's type up front - and then it enforces that promise on every
single row, forever.

```text
   CREATE TABLE orders (
     id          INTEGER,          ← whole numbers only
     customer    TEXT,             ← any text
     amount      DECIMAL,          ← money, kept exact
     ordered_at  DATE              ← real dates only; "March 1" with no year is rejected
   );
```

*What just happened:* You told the database the rules once. Now if anything tries to put the word "soon"
into `ordered_at`, the database refuses it instead of silently storing text that looks like a date. The
guard rail the spreadsheet never had is now built into the column itself.

📝 **Terminology.** A **constraint** is a rule the database enforces on a column - for example, "this
value can't be empty," or "every `id` must be unique." It's the database catching bad data at the door,
rather than you finding it three weeks later in a broken report. The whole class of bug where one stray
text cell silently breaks a `SUM`, or a part number loses its leading zeros, is simply gone - the wrong
shape isn't allowed in.

## Querying millions of rows

In Phase 1, the sheet slowed to a crawl and then hit a hard row ceiling. Databases are built for the
opposite: engineered to filter, sort, and summarize enormous tables quickly, because that's their entire
job. You don't drag a formula down a million rows - you write one sentence describing what you want, and
the database figures out how to get it fast. A `SELECT` query is you saying "give me these columns, from
this table, where these conditions hold."

```console
SELECT customer, amount
FROM orders
WHERE amount > 100;
```
```text
   customer   amount
   ────────   ──────
   Ada        250.00
   Grace      140.00
   Lin        199.50
```

*What just happened:* You asked one question - "show me the customer and amount for every order over
100" - and the database scanned the whole `orders` table and handed back only the matching rows. It does
the same whether the table has a hundred rows or a hundred million, and it doesn't melt your laptop doing
it. "The file is too big to open" stops being a sentence you say - bigger data is just a longer scan, not
a wall.

> The grammar of `SELECT … FROM … WHERE …` is the single most useful thing to learn here, and it has its
> own guide: [Querying Basics: SELECT & WHERE](/guides/querying-basics-select-where). If this is your
> first SQL query, read that next.

## Multiple users, safely

A shared spreadsheet lets several people edit at once, but resolves clashes crudely - often the last
save wins, quietly erasing someone else's change. Databases are designed from the start for many people
and programs reading and writing at once without trampling each other.

📝 **Terminology.** A **transaction** is a group of changes the database treats as all-or-nothing: either
every step succeeds, or none of them do. It's how a database moves money from one account to another
without ever leaving it half-moved - even if two people press "go" at the same instant.

*What just happened:* Where the spreadsheet's answer to "two people, same data" was "hope for the best,"
the database's answer is a set of rules that keep the data correct no matter how many people are touching
it - the difference between a tool for one person and a tool for a team. As soon as more than one person,
or one automated script, depends on your data, you need it to stay correct under simultaneous use. The
database gives you that for free; the spreadsheet never could.

## A worked move: the same task, leveled up

Picture the Phase 1 ritual: every Monday, opening a sheet of this week's orders and, by hand, filtering
to the big ones and eyeballing the total. In a database, that becomes a question you *ask*:

```console
SELECT customer, SUM(amount) AS total
FROM orders
WHERE ordered_at >= '2026-06-15'
GROUP BY customer;
```
```text
   customer   total
   ────────   ──────
   Ada        490.00
   Grace      140.00
```

*What just happened:* One query did the filtering and the per-customer totaling in a single step - no
dragging, no manual cleanup, reading the same live table everyone else does. Same result you used to
assemble by hand, now one repeatable sentence.

**Try it yourself.** Same idea on a tiny library dataset - join two tables and count, the kind of
question that would mean a fragile VLOOKUP in a sheet. Run it and tweak the `WHERE`:

```sql runnable
SELECT a.name AS author, a.country, COUNT(b.id) AS books
FROM authors a
JOIN books b ON b.author_id = a.id
GROUP BY a.id
ORDER BY books DESC;
```

And that word - *repeatable* - is the bridge to Phase 3. You've fixed size, types, and the source of
truth, but you're still the one running this query every Monday. What happens when even *that* should
run on its own?

## Recap

1. A **table** is a spreadsheet's ideas made sturdy: rows and columns, but with declared, enforced types.
2. A database gives you **one shared source of truth** - connections, not copies - so versions stop
   multiplying.
3. **Types and constraints** catch bad data at the door, killing the "stray text broke my SUM" class of
   bug.
4. Databases **query millions of rows** fast, and **SQL** (`SELECT … FROM … WHERE …`) is how you ask.
5. They handle **many users safely**, with transactions keeping data correct under simultaneous use.

You can now hold a clean, shared, queryable source of truth. Next: what to do when the querying itself
has to happen without you.
