This helps you add new data to a table but also update existing data if there is a conflict, all in one step.
When you want to add a new user but update their info if they already exist.
When importing data and you want to avoid duplicate entries.
When you want to keep a list updated without deleting and re-adding rows.
When you want to track inventory and update stock if the item is already listed.
Syntax
PostgreSQL
INSERTINTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_column) DO UPDATESET
column1 = EXCLUDED.column1,
column2 = EXCLUDED.column2;
-- ORINSERTINTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_column) DO NOTHING;
ON CONFLICT tells PostgreSQL what to do if the new data conflicts with existing data.
EXCLUDED refers to the new data you tried to insert.
Examples
Insert a user or update their name and email if the id already exists.
PostgreSQL
INSERTINTO users (id, name, email)
VALUES (1, 'Alice', 'alice@example.com')
ON CONFLICT (id) DO UPDATESET
name = EXCLUDED.name,
email = EXCLUDED.email;
Try to insert a product but skip if the sku already exists.
PostgreSQL
INSERTINTO products (sku, price)
VALUES ('ABC123', 9.99)
ON CONFLICT (sku) DO NOTHING;
Sample Program
This creates a table, adds one item, then tries to add the same item with a new quantity. Instead of error, it updates the quantity.
PostgreSQL
CREATETABLE inventory (
item_id SERIALPRIMARYKEY,
sku TEXT UNIQUE,
quantity INT
);
INSERTINTO inventory (sku, quantity) VALUES ('X123', 10);
-- Try to add same sku with new quantity, update if existsINSERTINTO inventory (sku, quantity) VALUES ('X123', 20)
ON CONFLICT (sku) DO UPDATESET quantity = EXCLUDED.quantity;
SELECT * FROM inventory;
OutputSuccess
Important Notes
You must have a unique constraint or primary key on the conflict column.
Use DO NOTHING to skip duplicates without error.
Use DO UPDATE to change existing rows with new data.
Summary
INSERT ON CONFLICT helps add or update data in one command.
It prevents errors from duplicate keys by updating or ignoring.
Use EXCLUDED to refer to the new data in updates.
Practice
(1/5)
1. What does the INSERT ON CONFLICT clause do in PostgreSQL?
easy
A. It inserts a new row or updates existing row if a conflict occurs.
B. It deletes rows that conflict with the new data.
C. It only inserts new rows and ignores conflicts without any update.
D. It creates a new table if a conflict is found.
Solution
Step 1: Understand the purpose and behavior of INSERT ON CONFLICT
This clause helps handle duplicate key conflicts during insert operations by allowing an update instead of error. It either updates the existing row or ignores the insert, preventing errors.
Final Answer:
It inserts a new row or updates existing row if a conflict occurs. -> Option A
Quick Check:
INSERT ON CONFLICT = Insert or update [OK]
Hint: Think: insert new or update existing on conflict [OK]
Common Mistakes:
Confusing ON CONFLICT with DELETE
Assuming it only inserts without update
Thinking it creates new tables
2. Which of the following is the correct syntax to update a column price on conflict for a table products with unique id?
easy
A. INSERT INTO products (id, price) VALUES (1, 100) ON CONFLICT DO NOTHING;
B. INSERT INTO products (id, price) VALUES (1, 100) ON DUPLICATE KEY UPDATE price = price + 1;
C. INSERT INTO products (id, price) VALUES (1, 100) ON CONFLICT (id) DO UPDATE SET price = EXCLUDED.price;
D. INSERT INTO products (id, price) VALUES (1, 100) ON CONFLICT (id) DO DELETE;
Solution
Step 1: Check PostgreSQL syntax for upsert and identify correct usage of EXCLUDED
PostgreSQL uses ON CONFLICT (column) DO UPDATE SET with EXCLUDED to refer to new values. INSERT INTO products (id, price) VALUES (1, 100) ON CONFLICT (id) DO UPDATE SET price = EXCLUDED.price; correctly uses EXCLUDED.price to update the price on conflict of id.
Final Answer:
INSERT INTO products (id, price) VALUES (1, 100) ON CONFLICT (id) DO UPDATE SET price = EXCLUDED.price; -> Option C
Quick Check:
Correct syntax uses ON CONFLICT (id) DO UPDATE SET with EXCLUDED [OK]
Hint: Use EXCLUDED.column to update on conflict [OK]
Common Mistakes:
Using MySQL syntax ON DUPLICATE KEY
Forgetting EXCLUDED keyword
Using DO DELETE which is invalid
3. Given the table users(id INT PRIMARY KEY, name TEXT, age INT) with data: (1, 'Alice', 30) What will be the result of this query?
INSERT INTO users (id, name, age) VALUES (1, 'Alice', 31) ON CONFLICT (id) DO UPDATE SET age = EXCLUDED.age RETURNING *;
medium
A. [] (empty result)
B. [{id:1, name:'Alice', age:31}]
C. Error: duplicate key value violates unique constraint
D. [{id:1, name:'Alice', age:30}]
Solution
Step 1: Understand the existing data/conflict and apply ON CONFLICT DO UPDATE
Row with id=1 exists with age=30, new insert tries age=31 causing conflict on id. It updates age to EXCLUDED.age (31) and returns the updated row.
Final Answer:
[{id:1, name:'Alice', age:31}] -> Option B
Quick Check:
ON CONFLICT updates age to 31 and returns updated row [OK]
Hint: ON CONFLICT updates existing row and returns it [OK]
Common Mistakes:
Expecting error on duplicate key
Thinking old age remains unchanged
Assuming empty result on update
4. Identify the error in this query:
INSERT INTO inventory (product_id, quantity) VALUES (10, 5) ON CONFLICT (product_id) DO UPDATE quantity = quantity + EXCLUDED.quantity;
medium
A. VALUES clause cannot be used with ON CONFLICT.
B. EXCLUDED keyword is not allowed in DO UPDATE.
C. ON CONFLICT must be followed by DO NOTHING, not DO UPDATE.
D. Missing SET keyword before update expressions.
Solution
Step 1: Review ON CONFLICT DO UPDATE syntax and identify missing SET keyword
The DO UPDATE clause requires SET keyword before specifying column updates. The query misses SET before 'quantity = quantity + EXCLUDED.quantity', causing syntax error.
Final Answer:
Missing SET keyword before update expressions. -> Option D
Quick Check:
DO UPDATE requires SET before column assignments [OK]
Hint: Remember DO UPDATE SET column = value [OK]
Common Mistakes:
Omitting SET keyword in DO UPDATE
Misusing EXCLUDED keyword
Confusing DO NOTHING and DO UPDATE
5. You want to insert a new user into users(id, name, score) but if the id exists, update the score only if the new score is higher. Which query correctly implements this?
hard
A. INSERT INTO users (id, name, score) VALUES (2, 'Bob', 50) ON CONFLICT (id) DO UPDATE SET score = EXCLUDED.score WHERE EXCLUDED.score > users.score;
B. INSERT INTO users (id, name, score) VALUES (2, 'Bob', 50) ON CONFLICT (id) DO UPDATE SET score = users.score WHERE EXCLUDED.score > users.score;
C. INSERT INTO users (id, name, score) VALUES (2, 'Bob', 50) ON CONFLICT (id) DO NOTHING WHERE EXCLUDED.score > users.score;
D. INSERT INTO users (id, name, score) VALUES (2, 'Bob', 50) ON CONFLICT (id) DO UPDATE SET score = EXCLUDED.score;
Solution
Step 1: Understand conditional update on conflict and use WHERE clause in DO UPDATE
You want to update score only if new score is greater than existing score. INSERT INTO users (id, name, score) VALUES (2, 'Bob', 50) ON CONFLICT (id) DO UPDATE SET score = EXCLUDED.score WHERE EXCLUDED.score > users.score; uses WHERE EXCLUDED.score > users.score to conditionally update score correctly.
Final Answer:
INSERT INTO users (id, name, score) VALUES (2, 'Bob', 50) ON CONFLICT (id) DO UPDATE SET score = EXCLUDED.score WHERE EXCLUDED.score > users.score; -> Option A
Quick Check:
Conditional update uses WHERE clause in DO UPDATE [OK]
Hint: Use WHERE in DO UPDATE for conditional changes [OK]
Common Mistakes:
Updating unconditionally without WHERE
Using DO NOTHING with WHERE (invalid)
Setting score to old value mistakenly
Recommended
Ready to prove it?
Pass the test and this pattern moves unknownstrongwhile earning +1 Grip toward your certificate.