Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Upsert in KnexJS

Tags:

I have an upsert query in PostgreSQL like:

INSERT INTO table
  (id, name)
values
  (1, 'Gabbar')
ON CONFLICT (id) DO UPDATE SET
  name = 'Gabbar'
WHERE
  table.id = 1

I need to use knex to this upsert query. How to go about this?

like image 251
myusuf Avatar asked Jul 29 '16 12:07

myusuf


People also ask

What is Upsert in PostgreSQL?

The UPSERT statement is a DBMS feature that allows a DML statement's author to either insert a row or if the row already exists, UPDATE that existing row instead. That is why the action is known as UPSERT (simply a mix of Update and Insert).

How do I Upsert in MySQL?

We can perform MySQL UPSERT operation mainly in three ways, which are as follows: UPSERT using INSERT IGNORE. UPSERT using REPLACE. UPSERT using INSERT ON DUPLICATE KEY UPDATE.

What is KNEX NPM?

js (pronounced /kəˈnɛks/) is a "batteries included" SQL query builder for PostgreSQL, CockroachDB, MSSQL, MySQL, MariaDB, SQLite3, Better-SQLite3, Oracle, and Amazon Redshift designed to be flexible, portable, and fun to use.


2 Answers

So I solved this using the following suggestion from Dotnil's answer on Knex Issues Page:

var data = {id: 1, name: 'Gabbar'};
var insert = knex('table').insert(data);
var dataClone = {id: 1, name: 'Gabbar'};

delete dataClone.id;

var update = knex('table').update(dataClone).whereRaw('table.id = ' + data.id);
var query = `${ insert.toString() } ON CONFLICT (id) DO UPDATE SET ${ update.toString().replace(/^update\s.*\sset\s/i, '') }`;

return knex.raw(query)
.then(function(dbRes){
  // stuff
});

Hope this helps someone.

like image 180
myusuf Avatar answered Sep 24 '22 23:09

myusuf


As of [email protected]+ a new method onConflict was introduced.

Official documentation says:

Implemented for the PostgreSQL, MySQL, and SQLite databases. A modifier for insert queries that specifies alternative behaviour in the case of a conflict. A conflict occurs when a table has a PRIMARY KEY or a UNIQUE index on a column (or a composite index on a set of columns) and a row being inserted has the same value as a row which already exists in the table in those column(s). The default behaviour in case of conflict is to raise an error and abort the query. Using this method you can change this behaviour to either silently ignore the error by using .onConflict().ignore() or to update the existing row with new data (perform an "UPSERT") by using .onConflict().merge().

So in your case, the implementation would be:

knex('table')
  .insert({
    id: id,
    name: name
  })
  .onConflict('id')
  .merge()
like image 27
Dorad Avatar answered Sep 22 '22 23:09

Dorad