SQL theory · page 5 of 10

Integrity and normalisation

Constraints, normal forms and B-tree indexes.

A database is only as good as the data in it. Constraints let the database refuse bad data, and normalisation designs tables so that each fact is stored once.

Constraints

ConstraintRefuses
NOT NULLa missing value
UNIQUEa second row with the same value
PRIMARY KEYa duplicate or missing identifier (unique and not null together)
FOREIGN KEY ... REFERENCESa value with no matching row in the other table
CHECK (condition)a row for which the condition is false

A foreign key can also say what happens when the referenced row is deleted: refuse (the default), ON DELETE CASCADE (delete the dependent rows too) or ON DELETE SET NULL.

Normalisation

Store each fact in one place, so it cannot disagree with itself. The first three normal forms are the ones used in practice:

  • First normal form: one value per column. Not a list of coverages in a text column, but one row per coverage.
  • Second normal form: every column depends on the whole key. In policy_coverages, keyed by policy and coverage, a coverage's name depends on the coverage alone, so it belongs in coverage_types.
  • Third normal form: no column depends on another non-key column. A customer's country depends on their region, so customers stores region_id and regions stores the country.

Reporting tables and views are often denormalised on purpose, repeating data to make queries simple and fast; the normalised tables stay the source of truth.

Indexes

An index is a separate, sorted structure that points to rows. PostgreSQL's default, the B-tree, finds a value in a few steps however large the table: a tree three or four levels deep covers millions of rows. Primary keys and unique constraints create one automatically; foreign keys do not, so a column used in joins, such as claims.policy_id, often needs one.

SELECT indexname, indexdef
FROM pg_indexes
WHERE tablename = 'claims';
The indexes on claims: the primary key's, and any you have made. Try it in the playground
Each index speeds up reading and slows down writing, because every insert and update must maintain it.
Practise it on Day 5

Check your understanding

Answer every question, then check.

1. Which constraint refuses a policy whose end date is before its start date?

2. Why does customers store region_id rather than the country itself?

3. Does PostgreSQL index a foreign key column automatically?

An unhandled error has occurred. Reload 🗙

Reconnecting…

Your connection to Data Analytics SQL Lab dropped, probably a Wi-Fi blip. Hold on while it reconnects. Your work is kept.

The connection could not be restored. The page will reload in a few seconds.