INSERT ON CONFLICT DO UPDATE using pg-promise helpers for multi row insert/update
Asked Answered
S

1

5

I am trying to insert multiple rows to pgsql database using pg-promise. In my case, few records, which I am trying to insert, may exist already in the table. In such case, I need to update them. By going through the pg-promise official documentaion, I found multiple rows can either be inserted or updated using helpers. Is there any way to do like below but for multiple inserts/updates?

INSERT INTO table_name(column_list) 
VALUES(value_list)
ON CONFLICT target action;
Sonnie answered 9/8, 2020 at 14:30 Comment(3)
Yes, just create the insert-values query using helpers, then tack on the ON CONFLICT … as a string.Uda
@Uda Yes, pretty much. I added my answer anyhow, might help a bit more :)Breuer
@Breuer Yeah, but I didn't know from the top of my head how it would look exactly, and I didn't know about assignColumns!Uda
B
9

Create your static variables somewhere:

const cs = new pgp.helpers.ColumnSet(['first', 'second', 'third', 'fourth'], 
                                      {table: 'my-table'});

// let's assume columns 'first' and 'second' produce conflict when exist:
const onConflict = ' ON CONFLICT(first, second) DO UPDATE SET ' +
    cs.assignColumns({from: 'EXCLUDED', skip: ['first', 'second']});

In the example below we assume your data is an array of valid objects:

const upsert = pgp.helpers.insert(data, cs) + onConflict; // generates upsert

await db.none(upsert); // executes the query:


Extras

If you want all SQL generated in upper case rather than low case, you can set option capSQL:

const pgp = require('pg-promise')({
  capSQL: true
});

And the best way to see what's generated and executed is with the help of pg-monitor.

Breuer answered 9/8, 2020 at 18:20 Comment(5)
What if your update is dependent on current value? Like first = my-table.first + EXCLUDED.first Should you just add it part of the onConflict query or can you do something with assignColumns?Creatine
@MariusMircea You would just have to append that manually, assignColumns is there only to simplify regular assignment, because that covers 99% of all practical cases. And what you are asking is fairly unique.Breuer
Works perfectly! For anyone like me who was confused at the use of 'EXCLUDED', it is a postgres syntax for accessing the row that we were unsuccessful in inserting postgresql.org/docs/current/sql-insert.htmlAndel
Is there any method to have the count of rows updated and the count of rows created returned? I see using db.result() we receive rowCount however nothing to specify columns which hit the conflict.Polypetalous
thanks mate this is gold! I have never worked with pg but this is awesome!Overlook

© 2022 - 2024 — McMap. All rights reserved.