Columns

ALTER COLUMN ... SET NOT NULL

Lock mode ACCESS EXCLUSIVE
Risk MEDIUM
Blocks reads, writes, other DDL
ALTER TABLE orders ALTER COLUMN customer_id SET NOT NULL;

What this does

Postgres must confirm no existing row is NULL, which is a full table scan held under ACCESS EXCLUSIVE unless a previously validated CHECK constraint already proves it (PostgreSQL 12+ can skip the scan in that case, but the lock is still taken).

Safe rewrite

Add a CHECK constraint as NOT VALID, validate it (non-blocking), then SET NOT NULL skips the scan

-- Migration 1: add constraint without validating (brief ACCESS EXCLUSIVE lock)
ALTER TABLE orders ADD CONSTRAINT chk_customer_id_nn CHECK (customer_id IS NOT NULL) NOT VALID;
-- Migration 2: validate (SHARE UPDATE EXCLUSIVE, allows reads and writes)
ALTER TABLE orders VALIDATE CONSTRAINT chk_customer_id_nn;
-- Migration 3: the validated CHECK lets Postgres skip the full table scan
ALTER TABLE orders ALTER COLUMN customer_id SET NOT NULL;
ALTER TABLE orders DROP CONSTRAINT chk_customer_id_nn;

Read more

More in Columns