Single query UPSERTs in PostgreSQL

Jari (LotU)
wehkamp-techblog
Published in
2 min readFeb 4, 2020

Let’s say you have an application that contains a request log. The log consists of 4 fields and is stored in a Postgres database. The table looks like this:

In our backend we want to use the same function to both update an existing request, or create a new one, based on if we pass in a value for ID.

Normally we’d have to write multiple queries to achieve this.
One to see if a row already exists, then based on that either UPDATE or INSERT

In this blog, we’ll explore how to achieve a so called UPSERT (update & insert) in just 1 query.

To achieve this, we will use Postgres’ ON CONFLICT statement along with a custom PSQL function. The function will manage the requests_id_seq so we don’t
a) get errors about missing data, and
b) get errors later on because the value returned from nextval('requests_id_seq') is not aligned with the table anymore.

The function used is:

This function achieves consists of a very simple IF statement that does the following:

  • If an ID is not passed in, the ID is set to the next value in the ID sequence.
  • If an ID is passed in and the ID is larger or equal to the highest ID currently in the table, the ID sequence is updated to be the next value after the passed in ID.

This makes sure that the ID is never null when creating the row and makes sure that updating or inserting a new ID manually doesn’t mess up the auto incrementing IDs.

Now the function has to be attached to the table, so it runs before every INSERT and UPDATE query:

Now that the setup is done, we can create the query that takes advantage of this function and allows our UPSERT.

The query consists of 2 parts:
1. The normal INSERT part of our query
2. The ON CONFLICT clause that morphs our INSERT into an UPDATE

To use this as a normal INSERT pass in (NULL, 'some_user', 'my request', 'to-do'), and swap out the NULL for an item ID to use the UPDATE.

I hope you found this useful, if you did maybe also check out the other posts on our tech-blog. Thanks for reading!

--

--

Jari (LotU)
wehkamp-techblog

Swift Developer丨WWDC 2017 & 2019 Scholarship winner丨Server Side Swift team @rwenderlich丨iOS Developer @wehkamp