Yuval Kaufman
Yuval Kaufman

Reputation: 677

How to Retrieve id of inserted row when using upsert with WITH cluase in Posgres 9.5?

I'm trying to do upset query in Postgres 9.5 using "WITH"

with s as (
            select id
            from products
            where product_key = 'test123'
        ), i as (
            insert into products (product_key, count_parts)
            select 'test123', 33
            where not exists (select 1 from s)
            returning id                       
        )
        update products
        set product_key='test123', count_parts=33
        where id = (select id from s) 
        returning id

Apparently I'm retrieving the id only on the updates and get nothing on insertions even though I know insertions succeeded.

I need to modify this query in a way I'll be able the get the id both on insertions and updates.

Thanks!

Upvotes: 2

Views: 898

Answers (1)

Kristo Mägi
Kristo Mägi

Reputation: 1684

It wasn't clear to me why you do at WITH first SELECT, but the reason you get only returning UPDATE id is because you're not selecting INSERT return.

As mentioned (and linked) in comments, Postgres 9.5 supports INSERT ON CONFLICT Clause which is a much cleaner way to use.

And some examples of before and after 9.5:

Before 9.5: common way using WITH

WITH    u AS (
            UPDATE      products
            SET         product_key='test123', count_parts=33
            WHERE       product_key = 'test123'
            RETURNING   id
        ),i AS (
            INSERT
            INTO        products ( product_key, count_parts )
            SELECT      'test123', 33
            WHERE       NOT EXISTS( SELECT 1 FROM u )
            RETURNING   id
        )
SELECT  *
FROM    (       SELECT id FROM u
        UNION   SELECT id FROM i
        ) r;

After 9.5: using INSERT .. ON CONFLICT

INSERT INTO products ( product_key, count_parts )
VALUES      ( 'test123', 33 )
ON CONFLICT ( product_key ) DO
UPDATE
SET         product_key='test123', count_parts=33
RETURNING   id;

UPDATE:

As hinted in a comment there might be slight cons using INSERT .. ON CONFLICT way.
In case table using auto-increment and this query happens a lot, then WITH might be a better option.
See more: https://stackoverflow.com/a/39000072/1161463

Upvotes: 1

Related Questions