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 TABLE
clause. - Second, specify the new column name, data type, and constraint in the
ADD COLUMN
clause.
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 inventory
Code 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 vendors
Code 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 vendors
Code 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 vendors
Code 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 values
Code 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
website
column without theNOT NULL
constraint. - Step 2. Update values for the existing rows to ensure that the
website
column does not containNULL
. - Step 3. Add the
NOT NULL
constraint to thewebsite
column.
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 vendors
Code 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 vendors
Code 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 vendors
Code 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 COLUMN
statement to add one or more columns to a table.