Summary: in this tutorial, you’ll learn how to use the PostgreSQLALTER TABLE ADD COLUMN statement to add a new column to a table.
Getting Started with the PostgreSQL ALTER TABLE ADD COLUMN statement #
Due to new requirements, you may need to add one or more columns to a table. In PostgreSQL, you can use the ALTER TABLE ... ADD COLUMN statement to do that.
Here’s the basic syntax of the statement:
ALTER TABLE table_name
ADD COLUMN new_column data_type constraint;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)In this syntax:
- First, provide the name of the table you want to add a column in the
ALTER TABLEclause. - Second, specify the new column name, data type, and constraint in the
ADD COLUMNclause.
The ALTER TABLE ... ADD COLUMN appends the new column at the end of the column list of the table.
PostgreSQL does not allow you to insert a new column at a specified position in the column list like MySQL. But there is a workaround that I will cover shortly.
If you want to add multiple columns at the same time, you can use multiple ADD COLUMN clauses:
ALTER TABLE table_name
ADD COLUMN new_column1 data_type constraint,
ADD COLUMN new_column2 data_type constraint,
ADD COLUMN new_column3 data_type constraint;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Creating a sample table #
First, open your terminal and connect to the PostgreSQL server using psql tool:
psql -U postgres -d inventoryCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Second, create a new table called vendors:
CREATE TABLE vendors (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(255) NOT NULL
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Third, show the vendors table:
\d vendorsCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
Table "public.vendors"
Column | Type | Collation | Nullable | Default
--------+------------------------+-----------+----------+------------------------------
id | integer | | not null | generated always as identity
name | character varying(255) | | not null |
Indexes:
"vendors_pkey1" PRIMARY KEY, btree (id)
Code language: PHP (php)Adding one column to a table #
First, add a new column called address to the vendors table:
ALTER TABLE vendors
ADD COLUMN address TEXT;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Second, show the table structure using the \d command:
\d vendorsCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
Table "public.vendors"
Column | Type | Collation | Nullable | Default
---------+------------------------+-----------+----------+------------------------------
id | integer | | not null | generated always as identity
name | character varying(255) | | not null |
address | text | | |
Indexes:
"vendors_pkey1" PRIMARY KEY, btree (id)Code language: PHP (php)The output shows the address column at the end of the column list of the vendors table.
Adding multiple columns to a table #
First, add two columns email and phone to the vendors table:
ALTER TABLE vendors
ADD COLUMN email VARCHAR(255) NOT NULL,
ADD COLUMN phone VARCHAR(25) NOT NULL;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Second, display the structure of the vendors table:
\d vendorsCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
Table "public.vendors"
Column | Type | Collation | Nullable | Default
---------+------------------------+-----------+----------+------------------------------
id | integer | | not null | generated always as identity
name | character varying(255) | | not null |
address | text | | |
email | character varying(255) | | not null |
phone | character varying(25) | | not null |
Indexes:
"vendors_pkey1" PRIMARY KEY, btree (id)Code language: PHP (php)The output shows the new email and phone columns at the end of the column list.
Adding a new column to a table with data #
First, insert three rows into the vendors table:
INSERT INTO
vendors (name, address, email, phone)
VALUES
(
'Samsung',
'129 Samsung-ro, Yeongtong-gu, Suwon-si, Gyeonggi-do, South Korea',
'[email protected]',
'+82-2-2255-0114'
),
(
'Apple',
'One Apple Park Way, Cupertino, CA 95014, USA',
'[email protected]',
'+1-408-996-1010'
),
(
'Google',
'1600 Amphitheatre Parkway, Mountain View, CA 94043, USA',
'[email protected]',
'+1-650-253-0000'
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Second, add a website column to the vendors table with a NOT NULL constraint:
ALTER TABLE vendors
ADD COLUMN website VARCHAR NOT NULL;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)PostgreSQL issues the following error:
ERROR: column "website" of relation "vendors" contains null valuesCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)When you add the website column, the default values of the column are NULL, which violates the NOT NULL constraint.
To make it work, you need to follow these steps:
- Step 1. Add the
websitecolumn without theNOT NULLconstraint. - Step 2. Update values for the existing rows to ensure that the
websitecolumn does not containNULL. - Step 3. Add the
NOT NULLconstraint to thewebsitecolumn.
Third, add the website column without the NOT NULL constraint:
ALTER TABLE vendors
ADD COLUMN website VARCHAR;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Fourth, verify the change:
\d vendorsCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
Table "public.vendors"
Column | Type | Collation | Nullable | Default
---------+------------------------+-----------+----------+------------------------------
id | integer | | not null | generated always as identity
name | character varying(255) | | not null |
address | text | | |
email | character varying(255) | | not null |
phone | character varying(25) | | not null |
website | character varying | | |
Indexes:
"vendors_pkey1" PRIMARY KEY, btree (id)Code language: PHP (php)Fifth, update the values in the website column for all rows:
UPDATE vendors
SET
website = 'https://www.samsung.com'
WHERE
name = 'Samsung';
UPDATE vendors
SET
website = 'https://www.apple.com'
WHERE
name = 'Apple';
UPDATE vendors
SET
website = 'https://www.google.com'
WHERE
name = 'Google';Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)If you have lots of data to update, you can write a script that reads data from an external source (an API, a CSV file, etc.) and loads it to the website column.
Sixth, add the NOT NULL constraint to the website column:
ALTER TABLE vendors
ALTER COLUMN website SET NOT NULL;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Finally, verify the changes:
\d vendorsCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
Table "public.vendors"
Column | Type | Collation | Nullable | Default
---------+------------------------+-----------+----------+------------------------------
id | integer | | not null | generated always as identity
name | character varying(255) | | not null |
address | text | | |
email | character varying(255) | | not null |
phone | character varying(25) | | not null |
website | character varying | | not null |
Indexes:
"vendors_pkey1" PRIMARY KEY, btree (id)Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)PostgreSQL ALTER TABLE ADD COLUMN – Adding a column at a specific position #
PostgreSQL does not support adding a new column at a specified position. Fortunately, you have a workaround:
- Step 1. Rename the existing table to a new one.
- Step 2. Recreate the table with the desired column order.
- Step 3. Copy data from the old table to the new table.
- Step 4. Drop the old table.
For example, we’ll add a contact_person after the phone column to the vendors table:
First, rename the vendors table:
ALTER TABLE vendors
RENAME TO vendors_copy;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Second, recreate the vendors table with the new contact_person column after the phone column:
CREATE TABLE vendors (
id INT GENERATED ALWAYS AS IDENTITY PRIMARY KEY,
name VARCHAR(255) NOT NULL,
address TEXT,
email VARCHAR(255) NOT NULL,
phone VARCHAR(25) NOT NULL,
contact_person VARCHAR(255),
website VARCHAR NOT NULL
);Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Third, copy data from the vendors_copy to the vendors table:
INSERT INTO
vendors (
id,
name,
address,
email,
phone,
contact_person,
website
)
OVERRIDING SYSTEM VALUE
SELECT
id,
name,
address,
email,
phone,
NULL,
website
FROM
vendors_copy;Code language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)The clause OVERRIDING SYSTEM VALUE allows insert values into the identity column with the GENERATED ALWAYS AS IDENTITY constraint.
The contact_person will have NULL as the default value.
Fifth, verify the column layout of the vendors table:
\d vendorsCode language: PostgreSQL SQL dialect and PL/pgSQL (pgsql)Output:
Table "public.vendors"
Column | Type | Collation | Nullable | Default
----------------+------------------------+-----------+----------+------------------------------
id | integer | | not null | generated always as identity
name | character varying(255) | | not null |
address | text | | |
email | character varying(255) | | not null |
phone | character varying(25) | | not null |
contact_person | character varying(255) | | |
website | character varying | | not null |
Indexes:
"vendors_pkey" PRIMARY KEY, btree (id)Code language: PHP (php)Finally, drop the old table vendors_copy:
DROP TABLE vendors_copy;Using a migration library #
When you want to add a column to a table in the production database, you should use a migration library so that your code and database structure go to the production simultaneously. If you change the table structure before changing our code, the app may not work as expected.
For example, if you have an API that inserts data into a table. The table has a new NOT NULL column, but the API does not require it. Other systems using API can pass the validation check in the application layer but fail when it reaches the database.
Summary #
- Use
ALTER TABLE ... ADD COLUMNstatement to add one or more columns to a table.