Insert Row if Not Exists in Table in PostgreSQL
In PostgreSQL, you may encounter situations where you want to insert a row into a table only if it does not already exist. This can prevent duplicate records and maintain data consistency. PostgreSQL provides several ways to achieve this functionality, such as using the INSERT ... ON CONFLICT
clause or a conditional INSERT
statement with a SELECT
query.
In this tutorial, we’ll explore how to insert a row into a table only if it doesn’t already exist, along with practical examples for different scenarios.
Method 1: Using INSERT … ON CONFLICT
The INSERT ... ON CONFLICT
statement allows you to handle conflicts that occur when a duplicate key violation happens. You can specify an alternative action, such as skipping the insert or updating the existing row.
Syntax:
INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_column)
DO NOTHING;
Example: Insert Row with ON CONFLICT
Let’s create a table named users
with a unique constraint on the email
column:
CREATE TABLE users (
user_id SERIAL PRIMARY KEY,
username VARCHAR(100) NOT NULL,
email VARCHAR(100) NOT NULL UNIQUE
);
Insert a row into the table:
INSERT INTO users (username, email)
VALUES ('Alice', 'alice@example.com');
Attempt to insert another row with the same email, but handle the conflict:
INSERT INTO users (username, email)
VALUES ('Duplicate Alice', 'alice@example.com')
ON CONFLICT (email)
DO NOTHING;
Query the table to verify the result:
SELECT * FROM users;
Explanation: The ON CONFLICT
clause prevents the second insert from adding a duplicate row. The existing row remains unchanged, and no error is raised.
Method 2: Using Conditional INSERT with NOT EXISTS
An alternative approach is to use a conditional INSERT
statement with a NOT EXISTS
subquery to check whether the row already exists.
Example: Insert Row with NOT EXISTS
Using the same users
table, let’s insert a row only if an email doesn’t already exist:
INSERT INTO users (username, email)
SELECT 'Bob', 'bob@example.com'
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE email = 'bob@example.com'
);
Attempt to insert another row with an existing email:
INSERT INTO users (username, email)
SELECT 'Duplicate Bob', 'bob@example.com'
WHERE NOT EXISTS (
SELECT 1 FROM users WHERE email = 'bob@example.com'
);
Query the table to verify the result:
SELECT * FROM users;
Result:
Explanation: The NOT EXISTS
subquery ensures that a row is only inserted if no row with the specified email already exists. If the email exists, the INSERT
statement does nothing.
Conclusion
PostgreSQL provides multiple ways to insert rows into a table only if they do not already exist. The INSERT ... ON CONFLICT
clause is simple and efficient for handling duplicate key conflicts, while the NOT EXISTS
approach offers more flexibility for complex conditions. Both methods help maintain data integrity and avoid duplicate records in your database.