public inbox for [email protected]  
help / color / mirror / Atom feed
From: Adrian Klaver <[email protected]>
To: Samuel Marks <[email protected]>
Cc: Juan Rodrigo Alejandro Burgos Mella <[email protected]>
Cc: pgsql-general <[email protected]>
Subject: Re: How do I upsert depending on a second table?
Date: Fri, 26 Sep 2025 15:17:02 -0700
Message-ID: <[email protected]> (raw)
In-Reply-To: <[email protected]>
References: <CAMfPbcbjTE6=yVJjAyiNU=kM24e-0oLo8S1ZZ7dJZy3UKq+b3g@mail.gmail.com>
	<CAHbZ42xv5f-DrCnhrszKzmLrTQzrw1=3OYSyfEzM9rPVXAy_MQ@mail.gmail.com>
	<CAMfPbcbuww3geDUFce+eQ2DEtg1n=qHQ3N=2LdZYdJ55cUUHBA@mail.gmail.com>
	<CAHbZ42zCptkYZi=QHaeDFHL9adPS1-nE6xoUC5QBa5VcF0dihA@mail.gmail.com>
	<[email protected]>
	<CAMfPbcZeOZCdosvokifS=Kj6seakGFNvM6vM3v8FQNho7v_7Og@mail.gmail.com>
	<[email protected]>

On 9/24/25 16:03, Adrian Klaver wrote:
> On 9/24/25 10:02, Samuel Marks wrote:
>> On Wed, Sep 24, 2025 at 10:13 AM Adrian Klaver 

> I don't have enough experience with below to come up with an off the top 
> of my head examples, but they look like they may offer alternatives.
> 
> MERGE:
> 
> https://www.postgresql.org/docs/current/sql-merge.html
> 

First time working with MERGE, so approach the below with caution:

CREATE TABLE org
(
     "name"      VARCHAR(50) PRIMARY KEY,
     owner       VARCHAR(50) NOT NULL
);


CREATE TABLE repo
(
     "id"           INTEGER PRIMARY KEY,
     full_name      VARCHAR(255) UNIQUE NOT NULL,
     org            VARCHAR(50)         NOT NULL REFERENCES org ("name")
);


INSERT INTO org(name, owner) VALUES ('org0', 'user0');

WITH t AS (SELECT
     *
FROM
     org
RIGHT JOIN
     (values(0 , 'org0/name0 by wrong user', 'org0', 'wrong_user'))
         AS v(id, full_name, org, user_name)
      ON
         org.name = v.org
      AND
         org.owner = v.user_name
)
MERGE INTO repo as r
USING t
ON
     r.org = t.name

WHEN MATCHED AND t.id = r.id THEN
     UPDATE  SET (id, full_name, org) = (t.id, t.full_name, t.org)
WHEN NOT MATCHED AND t.user_name = COALESCE(t.owner, '') THEN
     INSERT VALUES(t.id, t.full_name, t.org)

RETURNING r.*;

  id | full_name | org
----+-----------+-----
(0 rows)

MERGE 0


select * from repo ;
  id | full_name | org
----+-----------+-----

WITH t AS (SELECT
     *
FROM
     org
RIGHT JOIN
     (values(0 , 'org0/name0 by right user', 'org0', 'user0'))
         AS v(id, full_name, org, user_name)
      ON
         org.name = v.org
      AND
         org.owner = v.user_name
)
MERGE INTO repo as r
USING t
ON
     r.org = t.name

WHEN MATCHED AND t.id = r.id THEN
     UPDATE  SET (id, full_name, org) = (t.id, t.full_name, t.org)
WHEN NOT MATCHED AND t.user_name = COALESCE(t.owner, '') THEN
     INSERT VALUES(t.id, t.full_name, t.org)

RETURNING r.*;
  id |        full_name         | org
----+--------------------------+------
   0 | org0/name0 by right user | org0
(1 row)

MERGE 1

select * from repo ;
  id |        full_name         | org
----+--------------------------+------
   0 | org0/name0 by right user | org0

WITH t AS (SELECT
     *
FROM
     org
RIGHT JOIN
     (values(0 , 'org0/name0 by right user update', 'org0', 'user0'))
         AS v(id, full_name, org, user_name)
      ON
         org.name = v.org
      AND
         org.owner = v.user_name
)
MERGE INTO repo as r
USING t
ON
     r.org = t.name

WHEN MATCHED AND t.id = r.id THEN
     UPDATE  SET (id, full_name, org) = (t.id, t.full_name, t.org)
WHEN NOT MATCHED AND t.user_name = COALESCE(t.owner, '') THEN
     INSERT VALUES(t.id, t.full_name, t.org)

RETURNING r.*;
  id |            full_name            | org
----+---------------------------------+------
   0 | org0/name0 by right user update | org0
(1 row)

select * from repo ;
  id |            full_name            | org
----+---------------------------------+------
   0 | org0/name0 by right user update | org0
(1 row)


-- 
Adrian Klaver
[email protected]






view thread (8+ messages)

reply

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Reply to all the recipients using the --to and --cc options:
  reply via email

  To: [email protected]
  Cc: [email protected], [email protected], [email protected], [email protected]
  Subject: Re: How do I upsert depending on a second table?
  In-Reply-To: <[email protected]>

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

This inbox is served by agora; see mirroring instructions
for how to clone and mirror all data and code used for this inbox