Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Postgres 9.5 ON CONFLICT DO SELECT

While doing UPSERT in Postgres 9.5, is it possible to return null on INSERT success and return something ON CONFLICT?

I would like to something like this:

insert into "user" (timestamp, user_id, member_id) 
values ($1, $2, $3)
ON CONFLICT (user_id, member_id) 
DO select id from "user" where user_id = $2 returning user_id

The only purpose of selecting user_id is to return something (anything other than null) ON CONFLICT, and without writing to disk. I know that this can be done with ON CONFLICT DO UPDATE but it would involve writing to disk.

like image 284
Jimski Avatar asked Apr 01 '18 11:04

Jimski


People also ask

What does on conflict do PostgreSQL?

ON CONFLICT DO UPDATE updates the existing row that conflicts with the row proposed for insertion as its alternative action.

Does Postgres have Upsert?

PostgreSQL lets you either add or modify a record within a table depending on whether the record already exists. This is commonly known as an "upsert" operation (a portmanteau of "insert" and "update").

How does Postgres Upsert work?

In PostgreSQL, the UPSERT operation means either UPDATE or INSERT operation. The UPSERT operation allows us to either insert a row or skip the insert operation if a row already exists and update that row instead. Suppose you want to insert bulk data from one table to another table that already has some data.

What is insert on conflict?

The INSERT ON CONFLICT statement allows you to update an existing row that contains a primary key when you execute the INSERT statement to insert a new row that contains the same primary key. This feature is also known as UPSERT or INSERT OVERWRITE. It is similar to the REPLACE INTO statement of MySQL.


1 Answers

You could use CTE:

WITH cte AS (
   INSERT INTO "user"(timestamp, user_id, member_id)
   values ($1, $2, $3)
   ON CONFLICT (user_id, member_id) DO NOTHING
   RETURNING user_id
)
SELECT NULL AS result
WHERE EXISTS (SELECT 1 FROM cte)          -- success
UNION ALL
SELECT id 
FROM "user" 
WHERE user_id = $2 
  AND NOT EXISTS (SELECT 1 FROM cte);     -- conflict

DBFiddle Demo

like image 59
Lukasz Szozda Avatar answered Sep 20 '22 12:09

Lukasz Szozda