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.
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.
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 PostgreSQLINSERT 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.
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.
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.
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 type | How to write it | Example |
|---|---|---|
| Text (VARCHAR, TEXT) | Inside single quotes | 'Ana' |
| Whole number (INTEGER) | No quotes needed | 42 |
| Decimal number (NUMERIC) | No quotes needed | 19.99 |
| Date (DATE) | Single quotes, YYYY-MM-DD format | '2026-08-25' |
| True/false (BOOLEAN) | No quotes, lowercase | true |
| Empty / unknown value | The keyword NULL, no quotes | NULL |
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.
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.
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.
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.
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).
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.
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.
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.
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.
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.
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.
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.
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 projectOccasional, no-fluff notes on shipping modern software — startups, automation, Laravel, Shopify and more. No spam, unsubscribe anytime.
Keep reading
What is an index in SQL? A plain-English guide with copy-paste examples showing how indexes speed up queries and when you actually need one.
Learn JavaScript DOM manipulation for beginners: select elements, change text and styles, and handle clicks with simple, copy-paste code examples.
Let's build something
Book a free discovery call. We'll listen, ask sharp questions, and send you a proposal within 3 business days.