Several months ago I learned from an answer on Stack Overflow how to perform multiple updates at once in MySQL using the following syntax:
INSERT INTO table (id, field, field2) VALUES (1, A, X), (2, B, Y), (3, C, Z)
ON DUPLICATE KEY UPDATE field=VALUES(Col1), field2=VALUES(Col2);
I've now switched over to PostgreSQL and apparently this is not correct. It's referring to all the correct tables so I assume it's a matter of different keywords being used but I'm not sure where in the PostgreSQL documentation this is covered.
To clarify, I want to insert several things and if they already exist to update them.
I use this function merge
i was looking for the same thing when i came here, but the lack of a generic "upsert" function botherd me a bit so i thought you could just pass the update and insert sql as arguments on that function form the manual
that would look like this:
and perhaps to do what you initially wanted to do, batch "upsert", you could use Tcl to split the sql_update and loop the individual updates, the preformance hit will be very small see http://archives.postgresql.org/pgsql-performance/2006-04/msg00557.php
the highest cost is executing the query from your code, on the database side the execution cost is much smaller
Edit: This does not work as expected. Unlike the accepted answer, this produces unique key violations when two processes repeatedly call
upsert_foo
concurrently.Eureka! I figured out a way to do it in one query: use
UPDATE ... RETURNING
to test if any rows were affected:The
UPDATE
has to be done in a separate procedure because, unfortunately, this is a syntax error:Now it works as desired:
Similar to most-liked answer, but works slightly faster:
(source: http://www.the-art-of-web.com/sql/upsert/)
I custom "upsert" function above, if you want to INSERT AND REPLACE :
`
And after to execute, do something like this :
Is important to put double dollar-comma to avoid compiler errors
I have the same issue for managing account settings as name value pairs. The design criteria is that different clients could have different settings sets.
My solution, similar to JWP is to bulk erase and replace, generating the merge record within your application.
This is pretty bulletproof, platform independent and since there are never more than about 20 settings per client, this is only 3 fairly low load db calls - probably the fastest method.
The alternative of updating individual rows - checking for exceptions then inserting - or some combination of is hideous code, slow and often breaks because (as mentioned above) non standard SQL exception handling changing from db to db - or even release to release.