Postgres ALTER COLUMN TYPE Generator
Changing a column type in PostgreSQL is one statement, but whether it takes 5 milliseconds or locks a busy table for an hour depends entirely on the type pair. Pick the old and new type here and the generator writes the ALTER TABLE ... ALTER COLUMN ... TYPE statement with a correct USING expression, tells you whether PostgreSQL has to rewrite the whole table, and gives you a batched add-column / backfill / swap migration for the cases where a rewrite is not acceptable. It also emits queries that find dependent views, indexes and rows that would fail to convert. Runs entirely in your browser.
Do more than postgres alter column type generator — meet Chat2DB
Chat2DB is an AI-powered SQL client for Windows, macOS and Linux. Write SQL in natural language, format and optimize queries automatically, and manage MySQL, PostgreSQL, Oracle and 20+ other databases in one workspace.
How to use
- Enter the table and column, then choose the current type and the target type; the tool fills in a USING expression when a plain cast is not enough.
- Read the rewrite verdict: NO means a catalog-only change, YES means every row is rewritten under an ACCESS EXCLUSIVE lock.
- Copy the direct ALTER for small tables, or the zero-downtime script for large ones, and run the dependency and dry-run checks before you migrate.
Frequently asked questions
Does ALTER COLUMN TYPE rewrite the whole table in PostgreSQL?
Only when the new type is not binary coercible from the old one, or when a USING expression changes the stored values. Widening varchar(50) to varchar(200), converting varchar to text, or increasing numeric precision while keeping the scale are catalog-only changes that finish instantly. Converting text to integer, integer to bigint, or timestamp to timestamptz in a non-UTC session rewrites every row and rebuilds every index on the table while holding an ACCESS EXCLUSIVE lock, so reads and writes queue behind it.
When do I need a USING clause, and what should it contain?
PostgreSQL applies an assignment cast automatically when one exists between the two types; you need USING when there is no such cast or when the raw data needs cleaning first. Typical cases are text to numeric — where empty strings must become NULL, hence NULLIF(btrim(col), '')::numeric — text to boolean, where you map 'yes'/'no'/'1'/'0' explicitly, and timestamp to timestamptz, where col AT TIME ZONE 'UTC' states which timezone the naive values were in. Always run the dry-run count first: a single unconvertible row aborts the migration after all the work is done.
How do I change a column type without downtime on a large table?
Add a new nullable column of the target type, add a BEFORE INSERT OR UPDATE trigger that keeps it in sync with the old one, backfill existing rows in batches of a few thousand so each transaction is short, then rename both columns inside one short transaction guarded by SET lock_timeout so it fails fast instead of piling up locks. Drop the old column and the trigger once the application has been verified. This tool generates all five steps for you; Chat2DB, a free AI-powered SQL client, is a convenient place to run and monitor them — download at https://chat2db.ai/download or use https://app.chat2db.ai.
