php-crud-api icon indicating copy to clipboard operation
php-crud-api copied to clipboard

Possible to upsert (do INSERT ON DUPLICATE KEY UPDATE)?

Open customautosys opened this issue 6 years ago • 7 comments

Dear mevdschee, is it possible to do this? Otherwise I guess I will have to select and check first which will use more data.

customautosys avatar Feb 04 '18 10:02 customautosys

This is easy to build, but not easy to design. What verb should we use: "post", "put", "patch" or even "merge"? And what value should we return: rows affected vs. insert id?

mevdschee avatar Feb 04 '18 11:02 mevdschee

Dear mevdschee,

If you're going to add this, maybe I can suggest POST (since it is primarily an insert)?

Maybe it can return something in JSON?

Many thanks for considering this idea anyway!

customautosys avatar Feb 12 '18 17:02 customautosys

I build a PoC upsert function today with LINK-method. If anyone wants to take a look at it:

https://gist.github.com/mycaravam/7b298db541e042e85573921fe832afb2

As @mevdschee said: easy to build, harder to design. Its not fully tested yet, so use at own risk...

mycaravam avatar Jul 25 '18 12:07 mycaravam

I have no clue how to overcome the INSERT IGNORE query... i make bulk inserts (400-500 records), and lots of records will be duplicated in the table, exception gets thrown, and no insert is made... can u somehow merge the LINK implementation, or parametrize somehow the url query to insert the SQL strings? No PHP experience here, just using ur lib as a quick api on my server :)

roipeker avatar Jul 02 '19 03:07 roipeker

@roipeker this is by no means a trivial topic, please read this article:

https://www.depesz.com/2012/06/10/why-is-upsert-so-complicated/

My take away from the article is that there is no easy cross-database performant and correct solution and that it is better to make your application aware of the existence/absence of records.

mevdschee avatar Jul 03 '19 10:07 mevdschee

What about the ability to extend api.php implantation with custom endpoints to created custom queries/implementations?

roipeker avatar Jul 19 '19 00:07 roipeker

Here's how I think it can be done with MySQL.

INSERT INTO user_logins(username, password)
  VALUES ('Naomi', 'secret1'), ('James', 'secret2')
  ON DUPLICATE KEY UPDATE
    username = VALUES(username),
    password = VALUES(password);

As you can see it is almost identical to a regular INSERT. The ON DUPLICATE KEY UPDATE section is added, with an assignment for each field.

Regarding the verb/endpoint, I think it's best to have it exactly identical as the regular insert. To differentiate between an INSERT and UPSERT, a header could be used, perhaps:

crud-allow-upsert: true

Regarding the return-value, I'd just return the PK's just like with the regular insert. There may be cases when you'd like to know weather it was inserted or updated, but I think they are rare enough to ignore.

In short, the INSERT and UPSERT are identical except for the header, in which case the ON DUPLICATE KEY UPDATE section is appended.

Richie765 avatar Jun 12 '20 14:06 Richie765