skip to content

Codd's third rule requires systematic treatment of null values. What exactly does that rule require of an engine, and name a mainstream database behaviour that violates it.

level: middleimportance: should knowfreq 30%

answer

  1. one marker, all types, systematic
  2. distinct from 0, blank, empty string
  3. missing vs inapplicable — SQL has one, Codd wanted two
  4. Oracle: empty string stored as NULL
  5. no sentinel values like 1900-01-01

basics

~20 s

It requires one single marker for missing or inapplicable information, supported uniformly for every data type and independent of any real value such as zero or empty string. Oracle treating the empty string as NULL for character columns violates it.

solid answer

~50 s

Rule 3 says the system must support a distinct representation for **missing or inapplicable information**, handled **systematically** — the same marker, with the same meaning and the same rules, for every data type, and distinct from any legitimate value like zero, blank, or an empty string. Two requirements hide in that: *uniformity* (no per-type special cases) and *distinctness* (a null must never be confused with a real value). Violations in practice: - **Oracle** stores an empty character string as NULL, so 'known to be empty' and 'unknown' collapse into the same thing — a per-type special case and a loss of distinctness. - Engines disagree about whether nulls collide in **unique constraints** and how they **sort**, so nulls are not handled identically everywhere even within one product family. - The model itself only asks for one marker; Codd later argued you actually need two — *missing but applicable* versus *inapplicable* — which no SQL engine provides.

go deeper

for a junior

State the rule as 'one marker for absent data, for every type, never equal to zero or empty string', and know not to use sentinel values.

for a middle

Name a concrete violation (Oracle's empty string) and explain the missing-versus-inapplicable gap.

for a senior

Discuss portability and constraint behaviour: nulls in unique constraints, aggregates skipping nulls, and the cost of every nullable column as a branch in consumer code.

for a principal

Frame it as a schema-policy question — default columns to NOT NULL, and require the reason for absence to be modelled as data whenever it carries business meaning.

## What Rule 3 actually says Codd's third rule: *null values, distinct from the empty character string, a string of blank characters, and from zero or any other number, are supported for representing missing information and inapplicable information in a systematic way, independent of data type.* Unpack it into three separate demands. **1. A dedicated marker exists.** There must be a way to record 'no value here' that is not itself a value. Before this was standard, applications used sentinels — 0 for an unknown price, 1900-01-01 for an unknown date, the string 'N/A'. Sentinels corrupt aggregates (a 0 price drags an average down), collide with real data (0 is a legitimate price), and depend on every reader knowing the convention. **2. It is distinct from every real value.** Empty string, blank-padded string, zero, and the earliest date are all legitimate values. The null marker must be none of them. **3. It is systematic and type-independent.** The same marker, with the same behaviour, for integers, text, dates, booleans and user-defined types. No column type gets its own private convention. ## Two kinds of absence The rule text mentions both *missing information* (a value exists in the world but the database does not know it — an unrecorded phone number) and *inapplicable information* (no value can exist — the termination date of a currently employed person). SQL offers one NULL for both. Codd himself considered this insufficient and proposed two distinct marks in his later work; no mainstream engine implements that, so the distinction has to be modelled explicitly when it matters — for example a separate status column, or splitting the inapplicable case into its own table so the column simply does not exist for those rows. ## Where mainstream engines fall short - **Oracle collapses the empty string.** Assigning a zero-length string to a character column stores NULL. So 'the customer explicitly has no middle name' cannot be distinguished from 'we never asked'. This breaks both distinctness and type-independence, and it makes application code non-portable: the same logic behaves differently on Oracle than on other engines. - **Unique constraints disagree.** Under the SQL standard's default, multiple nulls do not conflict in a unique constraint, because two unknowns are not known to be equal. Some engines and some optional syntaxes treat nulls as colliding instead. Same marker, different behaviour — not systematic across products. - **Grouping and ordering treat nulls as comparable.** Grouping and DISTINCT put all nulls together as if they were equal, and sorting places them consistently first or last, even though the comparison rules say two nulls are not equal. Necessary and useful, but it is a documented exception rather than uniform behaviour. - **Aggregates skip nulls silently.** Aggregate functions ignore nulls, so an average over a column with missing values is an average of the known subset. That is a defensible choice, but a reader who assumes every row contributed will misread the result. ## Why the rule matters beyond trivia Every violation pushes work back into applications. If empty string and null are the same, code must handle both spellings of absence on every read and write. If the reason for absence matters to the business — unknown price versus deliberately unpriced, missing consent versus refused consent — the single marker is not enough and the schema has to encode the reason explicitly. The mature engineering position is: use the null marker for genuine absence, never use sentinel values, and when the *kind* of absence carries business meaning, model it as data rather than overloading one marker. A good candidate connects the rule to a concrete cost: a nullable column is a branch every consumer must handle, so declaring columns NOT NULL where the business truly requires a value is the cheapest correctness measure available.

  • Rule 3 mentions both missing and inapplicable information. If that distinction matters to the business, how would you model it?
    Model the reason explicitly rather than overloading one marker: add a status or reason column alongside the value, or move the inapplicable case into a separate table or subtype where the column does not exist at all. That keeps the meaning in data, queryable and constrainable, instead of in a convention every reader must remember.

saying these in an interview costs you the question

  • Saying NULL means zero or empty string — the rule exists precisely to keep them distinct.
  • Using sentinel values such as 0, -1 or 1900-01-01 for unknowns and calling it equivalent.
  • Assuming every engine treats empty string and NULL differently; Oracle does not.
  • Claiming SQL distinguishes missing from inapplicable information — it offers a single marker for both.

context