Phase 6 · Building tables and changing data · Topic 6.1

CREATE TABLE and ALTER TABLE

Must know

CREATE TABLE defines a new table — its name, its columns, their types and rules — and ALTER TABLE changes an existing table, for example by adding a column.

Not started

Step 1 Understand it

Why you need it. Before data can be stored, the needs to know its shape. Choosing the , types and keys well at the start saves painful fixes later, when the holds millions of .

New words in this topic (tap one to see what it means)

Watch it happen

AnimationCREATE TABLE sets the shape; ALTER TABLE changes it later
Read the animation as text
  1. CREATE TABLE defines the shape: a name, columns, a type for each, and rules (constraints). It creates no rows.
  2. INSERT (1, 'PaperCo') leaves country out, so the DEFAULT fills it in: 'UK'.
  3. INSERT (2, 'SoundWorks', 'Germany') gives every value, so no default is needed.

Picture it

flowchart LR
  C["CREATE TABLE<br/>new, empty table<br/>with columns and rules"] --> I["INSERT rows"]
  I --> A["ALTER TABLE<br/>add a column:<br/>every row gets the default"]
sets up the shape, fills it, and reshapes it later — the new column is added to every row that already exists.

The idea

CREATE TABLE lists each column with its type and any rules (): name TEXT NOT NULL. One column, or a group of columns, is the . gives a value to use when an INSERT doesn't mention the column. ALTER TABLE changes the table afterwards: ADD COLUMN, RENAME COLUMN, COLUMN. These commands change the structure (the ), not the rows, and they belong to the part of called .

The shape of it

sql
CREATE TABLE table_name (
  id     INTEGER PRIMARY KEY,
  column TYPE NOT NULL,
  other  TYPE DEFAULT value
);
ALTER TABLE table_name ADD COLUMN new_column TYPE;

Words in lower case are the parts you fill in.

How it works, step by step

  1. CREATE TABLE suppliers makes an empty table with three columns.
  2. supplier_id is the primary key: unique and never .
  3. country has DEFAULT 'UK', so an INSERT that leaves it out gets 'UK'.
  4. ALTER TABLE products ADD COLUMN in_stock … DEFAULT 1 adds the column to all 7 existing rows, each with 1.
  5. Neither command returns rows; a afterwards shows the effect.

Analogy

Designing a paper form before printing it: you decide the boxes (columns), what may be written in each (types), which ones must be filled in (), and which are pre-filled (DEFAULT). ALTER TABLE is printing a new version of the form with an extra box.

Where the analogy breaks

A reprinted form doesn't change the forms already filled in. ALTER TABLE does: adding a column adds it to every existing row (with its default or NULL), and on a huge table that can take a long time or lock it.

Worked examples

Create a table and use its default

sql
CREATE TABLE suppliers (
  supplier_id INTEGER PRIMARY KEY,
  name        TEXT NOT NULL,
  country     TEXT DEFAULT 'UK'
);
INSERT INTO suppliers (supplier_id, name) VALUES (1, 'PaperCo');
INSERT INTO suppliers VALUES (2, 'SoundWorks', 'Germany');
SELECT * FROM suppliers ORDER BY supplier_id;

2 rows

supplier_idnamecountry
1PaperCoUK
2SoundWorksGermany

The first INSERT names only two columns, so country takes its default.

Add a column to an existing table

sql
ALTER TABLE products ADD COLUMN in_stock INTEGER NOT NULL DEFAULT 1;
SELECT product_name, price, in_stock
FROM products
WHERE category = 'Electronics'
ORDER BY product_name;

2 rows

product_namepricein_stock
Headphones401
Phone case151

Every existing product gets in_stock = 1. A NOT NULL column added to a table with rows needs a DEFAULT.

Must-know points

  • CREATE TABLE: name, then each column with its type and rules, separated by commas.
  • Give every table a primary key.
  • DEFAULT fills a column when an INSERT leaves it out.
  • ALTER TABLE ADD / RENAME / DROP COLUMN changes the structure of an existing table.
  • CREATE, ALTER and DROP are DDL: they change the schema, not the data.

Common mistakes

  • No primary key, so duplicate rows can't be told apart or removed cleanly.
  • Adding a NOT NULL column without a DEFAULT to a table that already has rows — most databases refuse.
  • Storing several values in one column ('Pen, Mug'). Each column should hold one value — see .

In other databases

  • Auto-numbered ids: id INTEGER GENERATED ALWAYS AS IDENTITY (or SERIAL); AUTO_INCREMENT; IDENTITY(1,1); INTEGER PRIMARY KEY does it automatically.
  • SQLite's ALTER TABLE is limited (add, rename and drop column only). PostgreSQL can also change a column's type with ALTER COLUMN … TYPE.

Step 2 Go further (free, optional)

Optional. The notes above are written to be enough on their own. These free resources give a second explanation and more practice.

Step 3 Practise

Try each one yourself first: out loud, or written and run in the practice box below, which saves every query you run. Then open the answer and compare.

  1. ExplainSay what it does and when to use it, in plain words, with no notes.

    Explain what each part of the suppliers CREATE TABLE does.

    Show answer

    CREATE TABLE suppliers ( … ) makes a new, empty table called suppliers, with the columns listed in the brackets.

    • supplier_id INTEGER PRIMARY KEY: a whole-number column that identifies each row. Primary key means it must be unique and can't be NULL. (In SQLite, an PRIMARY KEY is also numbered automatically if you leave it out.)
    • name TEXT NOT NULL: a text column that must always have a value. An INSERT without a name is refused.
    • country TEXT DEFAULT 'UK': a text column that may be left out; if an INSERT doesn't mention it, it gets 'UK'.

    The statement changes the structure (the schema) and returns no rows. It is DDL.

  2. Writefrom a blank page, then run it

    Create a table reviews with a review id, a product_id that references products, a rating from 1 to 5, and a created date, then insert two rows and select them.

    Show answer

    Each rule from the question becomes a constraint: makes product_id point at a real product, keeps the rating between 1 and 5, and DEFAULT CURRENT_DATE fills in today's date if an insert leaves it out (here both inserts give a date, so the result is fixed).

    Try inserting a rating of 9: the database refuses it with "CHECK constraint failed: rating 1 5".

    sql
    CREATE TABLE reviews (
      review_id  INTEGER PRIMARY KEY,
      product_id INTEGER NOT NULL REFERENCES products(product_id),
      rating     INTEGER NOT NULL CHECK (rating BETWEEN 1 AND 5),
      created_on TEXT NOT NULL DEFAULT CURRENT_DATE
    );
    INSERT INTO reviews (review_id, product_id, rating, created_on) VALUES (1, 6, 5, '2024-03-02');
    INSERT INTO reviews (review_id, product_id, rating, created_on) VALUES (2, 3, 4, '2024-03-05');
    SELECT r.review_id, p.product_name, r.rating, r.created_on
    FROM reviews r
    JOIN products p ON p.product_id = r.product_id
    ORDER BY r.review_id;

    2 rows

    review_idproduct_nameratingcreated_on
    1Headphones52024-03-02
    2Mug42024-03-05
  3. Predictsay it before you run it

    After INSERT INTO suppliers (supplier_id, name) VALUES (3, 'MugMakers');, what country does MugMakers have?

    Show answer

    'UK'. The INSERT names only supplier_id and name, so country takes its DEFAULT. (Every run starts from the original database, so the below creates the suppliers table first.)

    sql
    CREATE TABLE suppliers (
      supplier_id INTEGER PRIMARY KEY,
      name        TEXT NOT NULL,
      country     TEXT DEFAULT 'UK'
    );
    INSERT INTO suppliers (supplier_id, name) VALUES (3, 'MugMakers');
    SELECT * FROM suppliers;

    1 row

    supplier_idnamecountry
    3MugMakersUK
  4. Edge casesSay what happens with NULLs, ties, duplicates or no rows at all, and fix it.

    What happens if you insert a supplier without a name? Try it, and explain the error.

    Show answer

    The database refuses the row: "NOT NULL constraint failed: suppliers.name". name has no DEFAULT, so leaving it out would make it NULL, and NOT NULL forbids that. The whole INSERT fails and nothing is stored.

    That is the point of the rule: a supplier without a name is bad data, and the database stops it at the door, whatever program sent it.

    sql
    CREATE TABLE suppliers (
      supplier_id INTEGER PRIMARY KEY,
      name        TEXT NOT NULL,
      country     TEXT DEFAULT 'UK'
    );
    INSERT INTO suppliers (supplier_id, country) VALUES (4, 'France');

    Error: NOT NULL constraint failed: suppliers.name

Practice box: write and run your answers here

Ctrl/⌘ + Enter runs it. Select part of the query to run only that part.

Step 4 Interview-ready, then prove it

Your interview answer

About 20 to 40 seconds, said out loud.

CREATE TABLE defines a table's columns, and constraints — a primary key, NOT NULL, defaults, foreign keys — and ALTER TABLE evolves it later, such as adding a column. I always give tables a primary key, choose types deliberately — for money, proper types for dates — and treat schema changes on big tables carefully, because adding or changing columns can rewrite or lock the table.

Follow-up questions

What is a schema?

The structure of the database: its tables, columns, types and constraints. Also, in PostgreSQL, a named group of tables inside a database.

How do you add a NOT NULL column to a table that already has data?

Give it a DEFAULT, or add it as nullable, fill in the values with , then add the NOT NULL rule.

Tick each check when you can do it without notes

A topic is finished when you pass all four checks, not when you have read it. Be strict: if you had to look at the notes, it is not ticked yet.

  • Explain Say what it does and when to use it, in plain words, with no notes.
  • Write Write the query from a blank page, then run it to check.
  • Predict Read a query and say which rows it returns before you run it.
  • Edge cases Say what happens with NULLs, ties, duplicates or no rows at all, and fix it.

0 of 4 checks ticked.

Saved in this browser. Back it up or move it to another device.