Alter Table

Learn how to use the PostgreSQL ALTER TABLE statement to add columns, drop columns, rename columns, change types, and manage constraints.

5 min read · Last updated: March 2026 · Back to overview

Quick Answer

ALTER TABLE modifies the structure of an existing PostgreSQL table. Common actions include ADD COLUMN, DROP COLUMN, RENAME COLUMN, ALTER COLUMN SET DEFAULT, ALTER COLUMN SET NOT NULL, ADD CONSTRAINT, and RENAME TO. Most actions take an ACCESS EXCLUSIVE lock on the table.

Spin up a Postgres database in 20 seconds with Vela.

Try Vela Sandbox

The ALTER TABLE statement is the primary way to modify the structure of an existing PostgreSQL table. It covers a wide range of operations: adding or removing columns, changing column types and defaults, enforcing or removing constraints, and renaming the table itself. Understanding which operations require a table rewrite or an exclusive lock is critical for production deployments.

Common ALTER TABLE actions

-- Add a column
ALTER TABLE table_name ADD COLUMN column_name datatype constraint;

-- Drop a column
ALTER TABLE table_name DROP COLUMN column_name;

-- Rename a column
ALTER TABLE table_name RENAME COLUMN column_name TO new_column_name;

-- Change column default
ALTER TABLE table_name ALTER COLUMN column_name SET DEFAULT value;
ALTER TABLE table_name ALTER COLUMN column_name DROP DEFAULT;

-- Change NOT NULL
ALTER TABLE table_name ALTER COLUMN column_name SET NOT NULL;
ALTER TABLE table_name ALTER COLUMN column_name DROP NOT NULL;

-- Add a CHECK constraint
ALTER TABLE table_name ADD CHECK (expression);

-- Add a named constraint
ALTER TABLE table_name ADD CONSTRAINT constraint_name constraint_definition;

-- Rename the table
ALTER TABLE table_name RENAME TO new_table_name;

ALTER TABLE examples

Set up a demo table:

DROP TABLE IF EXISTS links;
CREATE TABLE links (
  link_id SERIAL PRIMARY KEY,
  title   VARCHAR(512) NOT NULL,
  url     VARCHAR(1024) NOT NULL
);

Add, drop, and rename columns:

-- Add a boolean column
ALTER TABLE links ADD COLUMN active BOOLEAN;

-- Remove it
ALTER TABLE links DROP COLUMN active;

-- Rename title to link_title
ALTER TABLE links RENAME COLUMN title TO link_title;

Add a column with a default value:

ALTER TABLE links ADD COLUMN target VARCHAR(10);
ALTER TABLE links ALTER COLUMN target SET DEFAULT '_blank';

Insert a row — the default kicks in:

INSERT INTO links (link_title, url)
VALUES ('PostgreSQL Tutorial', 'https://neon.com/postgresql/');

SELECT * FROM links;
 link_id |       link_title        |               url                | target
---------+-------------------------+----------------------------------+--------
       1 | PostgreSQL Tutorial     | https://neon.com/postgresql/     | _blank
(1 row)

Add a CHECK constraint restricting the allowed target values:

ALTER TABLE links
ADD CHECK (target IN ('_self', '_blank', '_parent', '_top'));

Attempting an invalid value now raises an error:

INSERT INTO links (link_title, url, target)
VALUES ('PostgreSQL', 'http://www.postgresql.org/', 'whatever');
-- ERROR: new row for relation "links" violates check constraint "links_target_check"

Add a UNIQUE constraint and rename the table:

ALTER TABLE links ADD CONSTRAINT unique_url UNIQUE (url);
ALTER TABLE links RENAME TO urls;

ALTER TABLE tips

  • Adding a nullable column with no default is a metadata-only change in PostgreSQL and does not rewrite the table — it is safe to run on large production tables.
  • Adding a column with a non-volatile default (a constant value) is also metadata-only in PostgreSQL 11+.
  • Changing a column's data type or adding a NOT NULL constraint typically rewrites the table and takes an exclusive lock — plan these operations during low-traffic windows or use tools like pg_repack.
  • Use named constraints (ADD CONSTRAINT name ...) so you can drop them easily later with DROP CONSTRAINT name.

Reference: PostgreSQL documentation — ALTER TABLE.

Continue in Managing Tables: Rename Table.

Related in this section: PostgreSQL Data Types · Create Table · Select Into

Frequently Asked Questions

Does ALTER TABLE lock the table?

Most ALTER TABLE operations acquire an ACCESS EXCLUSIVE lock, which blocks all reads and writes until the operation completes. PostgreSQL 11+ made adding a column with a constant default a metadata-only operation that does not rewrite the table. For zero-downtime changes on large tables, consider using concurrent index creation, pg_repack, or online schema change tools.

How do I add a NOT NULL column to a table that already has rows?

You cannot directly add a NOT NULL column without a default to a non-empty table. Instead: (1) add the column without NOT NULL, (2) populate it with UPDATE statements, (3) then apply SET NOT NULL with ALTER TABLE ... ALTER COLUMN ... SET NOT NULL.

Can I add multiple columns in one ALTER TABLE statement?

Yes. Chain multiple ADD COLUMN clauses separated by commas: ALTER TABLE t ADD COLUMN col1 TEXT, ADD COLUMN col2 INT. This is more efficient than separate ALTER TABLE statements because it takes only one lock.

How do I drop a constraint by name?

Use ALTER TABLE table_name DROP CONSTRAINT constraint_name. You can find constraint names with \d table_name in psql or by querying information_schema.table_constraints.

Does renaming a table break views or foreign keys?

No. PostgreSQL automatically updates dependent objects such as views, foreign key constraints, and indexes when you rename a table with ALTER TABLE ... RENAME TO. The internal object IDs remain the same.