PostgreSQL Tutorial

Data Types

Querying & Filtering Data

Managing Tables

Modifying Data

Conditionals

Control Flow

Transactions & Constraints

Working with JOINS & Schemas

Roles & Permissions

Working with Sets

Subquery & CTEs

User-defined Functions

Important In-Built Functions

PostgreSQL PL/pgSQL

Variables & Constants

Stored Procedures

Working with Triggers

Working with Views & Indexes

Errors & Exception Handling

PostgreSQL - Upsert

In PostgreSQL, "upsert" is an informal term used to describe the process of inserting a new record if it doesn't exist, or updating the record if it does exist. The actual SQL command that provides this capability in PostgreSQL is INSERT ... ON CONFLICT.

The ON CONFLICT clause helps handle unique constraint violations. This can be useful, for instance, when you're dealing with scenarios where you might be receiving data in a non-linear fashion, or where records can be updated and inserted in an arbitrary order.

Syntax:

INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_target)
DO NOTHING;

-- OR

INSERT INTO table_name (column1, column2, ...)
VALUES (value1, value2, ...)
ON CONFLICT (conflict_target)
DO UPDATE SET column1 = value1, column2 = value2, ...;

Where:

  • conflict_target can be a column or a set of columns that have a unique constraint or a unique index.
  • The DO NOTHING action means no action will be taken if there's a conflict.
  • The DO UPDATE action allows you to specify how the existing row should be updated if there's a conflict.

Examples:

  1. Insert or Do Nothing:

    Suppose you have a table users with a unique constraint on the email column. If you want to insert a new user but do nothing if the user's email already exists:

    INSERT INTO users (name, email)
    VALUES ('John Doe', 'johndoe@example.com')
    ON CONFLICT (email)
    DO NOTHING;
    
  2. Insert or Update:

    Using the same users table, if you want to insert a new user or update the user's name if the email already exists:

    INSERT INTO users (name, email)
    VALUES ('John Doe', 'johndoe@example.com')
    ON CONFLICT (email)
    DO UPDATE SET name = EXCLUDED.name;
    

    Here, the EXCLUDED keyword represents the values of the row proposed for insertion. So, EXCLUDED.name refers to 'John Doe' from our VALUES clause.

Notes:

  • When using ON CONFLICT, ensure that the target table has a unique constraint or unique index on the conflict_target column(s). Otherwise, the upsert will not work as intended.

  • It's important to remember that upserts are atomic in PostgreSQL, meaning they'll either completely succeed or completely fail. This ensures data consistency even when multiple transactions are trying to upsert on the same rows simultaneously.

In summary, "upsert" operations in PostgreSQL (using the INSERT ... ON CONFLICT construct) allow for more flexible data insertion and updating by handling potential conflicts in a specified manner. This capability can be especially useful in scenarios where data can come in an unpredictable order or from multiple sources.

  1. PostgreSQL upsert example: Perform an upsert using the INSERT ON CONFLICT statement:

    INSERT INTO example_table (id, value)
    VALUES (1, 'new_value')
    ON CONFLICT (id) DO UPDATE SET value = 'updated_value';
    
  2. How to perform upsert in PostgreSQL: Use the INSERT ON CONFLICT statement to perform an upsert:

    INSERT INTO target_table (id, column1, column2)
    VALUES (1, 'value1', 'value2')
    ON CONFLICT (id) DO UPDATE SET column1 = 'updated_value1', column2 = 'updated_value2';
    
  3. Upsert with unique constraint in PostgreSQL: Perform an upsert with a unique constraint:

    INSERT INTO example_table (id, value)
    VALUES (1, 'new_value')
    ON CONFLICT ON CONSTRAINT unique_constraint_name DO UPDATE SET value = 'updated_value';
    
  4. Conflict resolution in PostgreSQL upsert: Define conflict resolution with the ON CONFLICT clause:

    INSERT INTO example_table (id, value)
    VALUES (1, 'new_value')
    ON CONFLICT (id) DO NOTHING;
    
  5. Upsert with multiple conditions in PostgreSQL: Perform an upsert with multiple conflict conditions:

    INSERT INTO example_table (id, value)
    VALUES (1, 'new_value')
    ON CONFLICT (id, column2) DO UPDATE SET value = 'updated_value';
    
  6. Returning values after upsert in PostgreSQL: Return values after an upsert operation:

    INSERT INTO example_table (id, value)
    VALUES (1, 'new_value')
    ON CONFLICT (id) DO UPDATE SET value = 'updated_value'
    RETURNING *;
    
  7. Batch upsert in PostgreSQL: Perform a batch upsert with the VALUES clause:

    INSERT INTO example_table (id, value)
    VALUES (1, 'new_value1'), (2, 'new_value2')
    ON CONFLICT (id) DO UPDATE SET value = EXCLUDED.value;
    
  8. Upsert vs MERGE in PostgreSQL: Compare upsert and MERGE (upsert-like) operations:

    MERGE INTO target_table USING source_table
    ON target_table.id = source_table.id
    WHEN MATCHED THEN UPDATE SET target_table.column1 = source_table.column1
    WHEN NOT MATCHED THEN INSERT (id, column1, column2) VALUES (source_table.id, source_table.column1, source_table.column2);