PostgreSQL
Database Management
SQL Queries
Data Insertion
Data Duplication

Insert, on duplicate update in PostgreSQL?

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

PostgreSQL, one of the most advanced open-source relational database systems, offers robust support for complex SQL operations. One common requirement in database management is handling scenarios where you attempt to insert a row that might already exist based on certain unique constraints. If such a row exists, you might want to update it instead of creating a new one. This is often referred to as "upsert" (update or insert). PostgreSQL addresses this need with the ON CONFLICT clause, introduced in version 9.5.

Understanding the ON CONFLICT Clause

The ON CONFLICT clause is used in an INSERT statement to specify an alternative action if the insertion would lead to a duplicate in unique constraint or primary key violation. This feature not only simplifies SQL scripts but also improves their performance by reducing the need for additional queries to check for existing data before insertion.

Syntax of ON CONFLICT

The basic syntax for using ON CONFLICT is as follows:

sql
1INSERT INTO table_name (column1, column2, ...)
2VALUES (value1, value2, ...)
3ON CONFLICT (constraint_column)
4DO NOTHING | DO UPDATE SET column1 = value1 [, column2 = value2 ...]
5WHERE condition;
  • DO NOTHING: This option tells PostgreSQL to take no action if a conflict occurs. It's useful when you simply want to ignore the duplicate entry.
  • DO UPDATE: This option tells PostgreSQL to update the existing record. You can specify which columns to update and even use expressions to set new values.

Example with ON CONFLICT

Consider a table named products with columns product_id, product_name, and quantity.

sql
1CREATE TABLE products (
2    product_id SERIAL PRIMARY KEY,
3    product_name VARCHAR(255) UNIQUE,
4    quantity INT
5);

Now, let’s see how to use ON CONFLICT during insertion:

sql
1INSERT INTO products (product_name, quantity)
2VALUES ('Widget', 10)
3ON CONFLICT (product_name)
4DO UPDATE SET quantity = products.quantity + EXCLUDED.quantity;

In this example, if a product named "Widget" already exists, instead of throwing an error, PostgreSQL will update its quantity by adding the quantity of the new entry to the existing one.

Detailed Use Cases and Considerations

Choosing the Conflict Target

The ON CONFLICT clause requires a conflict target. This target is either a column name or a set of columns which together are subject to a unique constraint. The constraint_column in the syntax refers to this target.

The EXCLUDED Table

In DO UPDATE, the EXCLUDED table is a special table used in PostgreSQL. It holds the proposed row for insertion as it originally appeared before any processing by INSERT. You can reference it to get the values originally proposed for insertion.

Conditional Upsert

You can condition the update using a WHERE clause within the DO UPDATE. This provides control over whether to perform an update based on specific conditions of the existing rows:

sql
1INSERT INTO products (product_name, quantity)
2VALUES ('Widget', 10)
3ON CONFLICT (product_name)
4DO UPDATE SET quantity = products.quantity + EXCLUDED.quantity
5WHERE products.quantity + EXCLUDED.quantity < 100;

In this example, the update will only occur if the resulting quantity is less than 100.

Performance Implications

Using ON CONFLICT properly can result in considerable performance improvements, especially in scenarios where conflict occurrences are common. It reduces the need for prior SELECT queries to check for potential duplicates, leading to fewer round trips to the database.

Summary Table

FeatureDescription
Conflict HandlingAllows specification of an alternative action if a conflict occurs
DO NOTHINGIgnores the write operation for the conflict row
DO UPDATEUpdates the conflicting row with new values
Conflict TargetMust specify which column/set of columns should be checked for conflict
PerformanceReduces unnecessary queries and possible round trips to the database

Conclusion

The ON CONFLICT clause in PostgreSQL offers a powerful way to handle duplicates during insertion, enabling more efficient and cleaner data management procedures. Its ability to conditionally decide between insertion and update in a single operation simplifies code and improves database throughput.


Course illustration
Course illustration

All Rights Reserved.