All rules Rule SL005 · CN
SQLite · beta
warning
CN · Constraints & keys
free in the CLI, --engine=sqlite

Why does SQLite refuse ADD COLUMN REFERENCES with a non-NULL default?

ADD COLUMN REFERENCES with a non-NULL default

Warning: it works, but holds the single write lock or breaks the previous release.

What happens

When foreign keys are enforced (PRAGMA foreign_keys=ON, which most applications set on every connection), a column added with a REFERENCES clause must default to NULL, anything else fails with "Cannot add a REFERENCES column with non-NULL default value". Whether it fails depends on a per-connection pragma, so the same file passes in one runner and stops in another.

Why it is dangerous on a populated table

SQLite holds one write lock for the whole database, so anything that rebuilds a table blocks every writer for as long as the copy takes, and that time grows with the table.

Fires on

ALTER TABLE orders ADD COLUMN warehouse_id INTEGER REFERENCES warehouses(id) DEFAULT 1;

The safe pattern

Add the referencing column with a NULL default, backfill the rows that need a value, and let the application set it from then on.

ALTER TABLE orders ADD COLUMN warehouse_id INTEGER REFERENCES warehouses(id);
-- backfill from the application, in batches

Fixtures

The rule ships with these files and the test suite runs them on every change: the first set must fire, the second must stay silent.

Fires (1)

references default
ALTER TABLE orders ADD COLUMN warehouse_id INTEGER REFERENCES warehouses(id) DEFAULT 1;

Stays silent (2)

default without references
ALTER TABLE orders ADD COLUMN warehouse_id INTEGER DEFAULT 1;
references null
ALTER TABLE orders ADD COLUMN warehouse_id INTEGER REFERENCES warehouses(id);

How to check locally

Catch this before it ships

SQLite support is in beta: this rule runs locally in the free CLI, static only, and not in the hosted service yet. No install, nothing leaves your machine:

npx bolvrk check migration.sql --engine=sqlite