All posts
PostgreSQLAugust 25, 20267 min read

How to Insert Data Into a PostgreSQL Table (Guide)

Learn how to insert data into a PostgreSQL table with the INSERT INTO statement. Beginner-friendly examples for single rows, multiple rows, and auto IDs.

F
Fepiq Team
Fepiq

How do you insert data into a PostgreSQL table? You use the INSERT INTO statement: you name the table, list the columns you want to fill in, and then supply the values in the same order. For example, INSERT INTO users (name, email) VALUES ('Ana', 'ana@example.com'); adds one new row to the users table. In this guide, you will learn the exact syntax, how to insert several rows at once, how auto-generated IDs work, and the mistakes almost every beginner makes at first.

This guide assumes you already have an empty table waiting for data. If you have not created one yet, start with our guide on how to create a table in PostgreSQL, then come back here.

New to PostgreSQL? Learn how to create your first table before inserting data into it.

Read: How to Create a Table in PostgreSQL

What is the INSERT INTO statement?

INSERT INTO is a SQL command that adds a new row (a new record) to a table. Think of a table like a spreadsheet: each row is one entry, and each column is one piece of information about that entry. The INSERT INTO statement is how you add a new entry to that spreadsheet using code instead of typing into cells by hand.

The basic INSERT INTO syntax

Let's say you have a table called users with three columns: id, name, and email. Here is the simplest way to add one row to it.

sql
INSERT INTO users (name, email)
VALUES ('Ana', 'ana@example.com');

Line by line: INSERT INTO users tells PostgreSQL which table to add a row to. (name, email) lists exactly which columns you are providing values for — you do not have to mention every column, only the ones you're filling in. VALUES ('Ana', 'ana@example.com') supplies the actual data, in the same order as the column list: 'Ana' becomes the name, and 'ana@example.com' becomes the email. The line ends with a semicolon (;), which tells PostgreSQL the statement is finished.

Text, numbers, and dates: how to write each one correctly

A common beginner mistake is formatting a value incorrectly. PostgreSQL is strict about this, and getting it wrong causes an error. Use this table as a quick reference.

Data typeHow to write itExample
Text (VARCHAR, TEXT)Inside single quotes'Ana'
Whole number (INTEGER)No quotes needed42
Decimal number (NUMERIC)No quotes needed19.99
Date (DATE)Single quotes, YYYY-MM-DD format'2026-08-25'
True/false (BOOLEAN)No quotes, lowercasetrue
Empty / unknown valueThe keyword NULL, no quotesNULL

Notice that text and dates need single quotes, while numbers and true/false values do not. If you wrap a number in quotes, like '42', PostgreSQL will usually still accept it, but it is best to follow the correct format so your data stays predictable.

Inserting multiple rows at once

Writing a separate INSERT statement for every row works, but it is slow when you have many rows to add. PostgreSQL lets you insert several rows in a single statement instead.

sql
INSERT INTO users (name, email)
VALUES
  ('Ana', 'ana@example.com'),
  ('Ben', 'ben@example.com'),
  ('Chen', 'chen@example.com');

This is the same statement as before, but instead of one set of values in parentheses, we list three, separated by commas. Each parenthesis-wrapped group is one new row. PostgreSQL inserts all three rows in one go, which is faster and easier to read than three separate statements.

Letting PostgreSQL generate IDs for you

Most tables have an id column that uniquely identifies each row. If that column was created as SERIAL, BIGSERIAL, or GENERATED ... AS IDENTITY, PostgreSQL fills it in automatically — you should not, and usually cannot cleanly, supply your own value.

sql
CREATE TABLE users (
  id SERIAL PRIMARY KEY,
  name TEXT,
  email TEXT
);

INSERT INTO users (name, email)
VALUES ('Dana', 'dana@example.com');

The CREATE TABLE line defines id as SERIAL, which means PostgreSQL keeps an internal counter and assigns the next number automatically every time a row is inserted. Because of that, the INSERT statement below it only mentions name and email — it leaves id out completely, and PostgreSQL fills it in on its own (1, then 2, then 3, and so on).

Checking what you just inserted with RETURNING

Sometimes you want to see the row you just added right away, especially to grab the auto-generated id. The RETURNING keyword does this in a single step, without needing a separate SELECT query.

sql
INSERT INTO users (name, email)
VALUES ('Eli', 'eli@example.com')
RETURNING id, name;

This is the same INSERT statement as before, with one line added: RETURNING id, name. Instead of just silently adding the row, PostgreSQL now also prints back the id and name of the row it just created. This is especially useful in an app, where your code often needs to know the new row's id right after creating it.

Common mistakes beginners make with INSERT

  • Forgetting quotes around text or dates, e.g. writing Ana instead of 'Ana', which causes a "column does not exist" error because PostgreSQL thinks Ana is a column name.
  • Mismatching the number of columns and values — every column you list must have exactly one matching value, in the same order.
  • Trying to insert a value into an auto-generated id column, which usually is not necessary and can cause future inserts to clash with a duplicate id.
  • Leaving out a required column that has no default value, which triggers a "null value in column violates not-null constraint" error.
  • Forgetting the semicolon at the end of the statement, especially when running multiple statements in the same script.

What to do after inserting data

Once your table has data in it, the next step is reading it back out. That's done with the SELECT statement, which lets you ask for specific rows and columns using conditions like WHERE. Our SQL SELECT and WHERE guide covers exactly that, using the same beginner-friendly approach.

Frequently asked questions

How do I insert data into a PostgreSQL table?+

Use the INSERT INTO statement: name the table, list the columns in parentheses, then use VALUES followed by the actual data in matching parentheses. For example: INSERT INTO users (name, email) VALUES ('Ana', 'ana@example.com');. Don't forget the semicolon at the end.

Do I need to specify every column when inserting a row?+

No. You only need to list the columns you're providing values for. Any column you leave out will get its default value, or NULL if it allows empty values and has no default. Columns marked NOT NULL without a default must be included, or the insert will fail.

Can I insert multiple rows in one PostgreSQL statement?+

Yes. List several value groups after VALUES, separated by commas, like VALUES ('Ana', 'a@x.com'), ('Ben', 'b@x.com');. PostgreSQL inserts all of them in a single statement, which is faster than running INSERT separately for each row.

Why does my INSERT fail with a column does not exist error?+

This almost always means a text value is missing its single quotes. PostgreSQL then reads the word as a column or table name instead of as text. Wrapping it in quotes, like 'Ana' instead of Ana, fixes the error.

How do I get the id of the row I just inserted?+

Add RETURNING id to the end of your INSERT statement, before the semicolon. PostgreSQL will send back the newly generated id (and any other columns you list) right after the insert completes, without needing a separate SELECT query.

Building something that needs a real PostgreSQL database behind it? We design and build custom web apps end to end.

Talk to Fepiq about your project

Get new posts in your inbox

Occasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.

Keep reading

Related posts

All posts

Let's build something

Ready to ship your next product with Fepiq?

Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.