Skip to content

Mental model ​

A table is basically a typed array of objects. A row is one object. A column is a field. That's the whole plot twist.

Tables ≈ collections ​

In JS you might hold contacts like this:

ts
const contacts = [
  { id: 1, name: 'Ada Lovelace', email: 'ada@example.com', companyId: 10 },
  { id: 2, name: 'Grace Hopper', email: 'grace@example.com', companyId: 10 },
]

In SQL that collection is a table. Each object is a row. Each property is a column.

sql
-- conceptual shape
-- contacts(id, name, email, company_id)

As you can see, it's not magic. Same data, stricter shape, lives on disk (or in a server DB).

Schema vs "just objects" ​

In TypeScript you might write:

ts
type Contact = {
  id: number
  name: string
  email: string
  companyId: number | null
}

SQL's version is the table definition:

sql
CREATE TABLE contacts (
  id INTEGER PRIMARY KEY,
  name TEXT NOT NULL,
  email TEXT NOT NULL,
  company_id INTEGER
);

Comments for the code above:

  • PRIMARY KEY - unique row identity (like your React key, but enforced)
  • NOT NULL - required field
  • company_id can be null here - contact without a company is allowed

The schema is the contract. The database will refuse rows that break it (depending on constraints - we'll add more later).

Rows are not nested by default ​

Here's the FE trap.

In JSON APIs we love nesting:

json
{
  "id": 1,
  "name": "Ada Lovelace",
  "company": { "id": 10, "name": "Analytical Engines Inc" }
}

In the database, that's usually two tables linked by an id:

text
companies:  id=10, name=Analytical Engines Inc
contacts:   id=1, name=Ada, company_id=10

The nest happens at query time with a JOIN (or in the API/ORM layer). Flat storage, nested presentation.

Query = ask a question ​

FE vibeSQL vibe
contacts.filter(c => c.companyId === 10)WHERE company_id = 10
contacts.slice(0, 20)LIMIT 20
contacts.sort((a,b) => a.name.localeCompare(b.name))ORDER BY name
contacts.map(c => c.email)SELECT email FROM contacts
nested company includeJOIN companies …

We'll go through each of those for real in the next chapters.

One more thing: set-based thinking ​

JS often loops row by row. SQL thinks in sets - "give me all rows matching X, then sort them, then take 20".

That's why SQL can feel weird at first if you're used to for loops. Lean into it. The database is really good at set operations.

Next: SELECT basics.

Notes-style SQL tutorial for front-end folks