Skip to content
EL
Contents

Relational database concepts

Review a schema

DecisionFoundation4 min read15 min hands-on#fundamentals#sql#data-modeling

The idea in 30 seconds

Most schema mistakes come from storing a fact in the wrong shape: a list squeezed into one column, or the same fact copied into several tables. Both look convenient on day one. Both mean the database can no longer check your data, and every query has to work around the shape.

Helps to know first: What data is, and why we need a database

On this page

The situation

A small team is starting an online shop and asks an AI assistant for a schema. Customers place orders; each order contains one or more products. This is what came back.

Review taskOrders schema for a new shop

Pull request: “Simple orders schema. One table per order keeps it fast: no joins needed to show an order.”

CREATE TABLE customers (
  id     integer PRIMARY KEY,
  name   text,
  email  text
);

CREATE TABLE orders (
  id              integer PRIMARY KEY,
  customer_email  text,          -- copied so we can show it without a join
  customer_name   text,          -- same
  product_ids     text,          -- e.g. '1,2,5'
  total           numeric
);

Would you approve it? Write the review you would leave.

Your call

How to review a schema

Ask these questions of every table, in this order:

  1. What is one row? “One customer”, “one product in one order”. If you cannot say it in a few words, the table is doing two jobs.
  2. What identifies a row? That is the primary key. If the honest answer is “nothing”, rows can be duplicated and never told apart.
  3. Is any column holding a list? Comma-separated ids, JSON arrays of ids, phone1, phone2, phone3. A list usually wants its own table.
  4. Is any fact stored twice? Copies drift. Prefer a key that points to the one true copy, unless you have a measured reason to copy, and a plan to keep the copy in sync.
  5. What must always be true? Required values, uniqueness, references to other tables, allowed ranges. Write each as a constraint, so the database enforces it instead of every program remembering to.

Check yourself

  1. Why can’t a foreign key protect a product_ids column holding '1,2,5'?

    Show answer

    To the database the column is one text value, not three references. A foreign key compares whole column values against another table’s key, so it has nothing to check inside a string.

  2. What goes wrong when an order stores a copy of the customer’s email?

    Show answer

    The copy does not change when the customer updates their email. Old orders keep the old address and nothing marks which value is current.

  3. What should you ask first about any table, and why?

    Show answer

    “What is one row?” If one row cannot be described simply, the table mixes several kinds of thing, which leads to lists in columns, duplicated facts and missing keys.

Finished reading?

Saved in this browser only.

Sources

Where each claim on this page comes from.

  1. 1.
    PostgreSQL documentation: 5.5 Constraints
    Primary· §5.5.5 Foreign Keys

    A foreign key requires every value to match a row in the referenced table.

  2. 2.
    PostgreSQL documentation: 5.5 Constraints
    Primary· §5.5.4 Primary Keys

    A primary key can span several columns.

Go further

What to read next, and why it is worth the time.

  1. 1.
    PostgreSQL documentation: 5.5 Constraints
    Primary· §5.5 Constraints

    Every kind of rule the database can enforce for you. Knowing the list is half of reviewing a schema.

Applies to PostgreSQL 18. Draft: not yet fact-checked end to end.