I would suggest using the PostgreSQL way: https://www.postgresql.org/docs/9.5/static/sql-insert.html
INSERT INTO ... ON CONFLICT [(<column name>)] DO UPDATE SET foo = ... , bar = ... ; This approach is really cool, because we can specify which key is more important and discard other conflicts as an error. For example, given the following table: CREATE TABLE foo( id INTEGER NOT NULL, foo_key TEXT NOT NULL, some_data TEXT, PRIMARY KEY(id), UNIQUE (foo_key) ); INSERT INTO foo(id, foo_key, some_data) VALUES(1, "XXX", "..."); INSERT INTO foo(id, foo_key, some_data) VALUES(2, "YYY", "..."); If we are performing a query: INSERT INTO foo(id, foo_key, some_data) VALUES(1, "YYY", "...") <OR UPDATE ...> Which record should we update and what columns? Having the ability to specify a specific column on which the conflict is actually an acceptable event lets the developer to make a decision how to resolve it: INSERT INTO foo(id, foo_key, some_data) VALUES(1, "YYY", "...") <ON CONFLICT (foo_key) DO UPDATE SET some_data = "..."> 19 March 2018, 18:41:34, by "R Smith" <ryansmit...@gmail.com>: > On 2018/03/19 1:50 PM, Olivier Mascia wrote: > > > > I don't know what any 'standard' SQL defines about this. > > I know that FirebirdSQL (where I came from, before meeting SQLite) did/does > > it this way: > > > > UPDATE OR INSERT INTO > > {tablename | viewname} [(<columns>)] > > VALUES (<values>) > > [MATCHING (<columns>)] > > [RETURNING <values> [INTO <variables>]] > > Quite right, and the statement in MSSQL is even more convoluted, which, > if it was in SQLite like this, would require a dynamically created SQL > statement that is worse than simply computing an UPDATE and an INSERT - > which a previous poster already lamented. > > My suggestion for UPSERT would be the very simple already SQLite-like > syntax of: > > INSERT OR UPDATE INTO t (k1, k2, ... , kn, f1, f2, ... , fn) > followed by the usual VALUES clause or SELECT query. > > Any record found to exist with the exact same value in the Primary Key > field(s) [ k1 .. kn ] has all other fields (that are NOT Primary Key > fields) updated to the new values, and if no such record is found, the > row simply gets inserted. If the inserted row OR updated values cause > any other constraint to break, then FAIL hard, the same way (and > possibly with the same ON CONFLICT options) as any other single INSERT > or UPDATE would be subjected to. > > This is far better than INSERT OR REPLACE since there is no delete, and > no multiple-row delete on constraint violations. > It is simple in terms of converting any current INSERT OR REPLACE query > to an INSERT OR UPDATE query requires changing 1 word only. > > Triggers should fire for ON INSERT and ON UPDATE according to whatever > actually is required during the operation. > > Adding this has no backward compatibility to break, this did not exist > before and it is not schema-specific. > > > One possible added refinement might be an optional second field-group > that should be ignored over-and-above the PK fields during the UPDATE. > (During the INSERT of course all fields MUST be added). > > 2 ways this can be done easily: > > A - Use a separate 2nd prototype group for Non-Updating fields, Like > this perhaps: > > INSERT OR UPDATE INTO t (pk1, pk2, f1, f2, f3, f4) NOT (f1, f2) VALUES > (...); -- This example updates only f3 and f4 if the record already exists. > > I just picked "NOT" as the separator, perhaps "KEEP" gives better > clarity (see next example), but any good word would do. > Primary key fields pk1 and pk2 along with specified non-updating fields > f1 and f2 are all ignored during an update, but still used during an > insert. > Adding a PK field to the second set is a no-op as some might like it for > legibility. i.e this next query is equivalent to the above: > > INSERT OR UPDATE INTO t (pk1, pk2, f1, f2, f3, f4) KEEP (pk1, pk2, f1, > f2) VALUES (...); -- This example updates only f3 and f4, same as above. > > > B - Use a Marker of sorts for Non-Updating fields, Like this perhaps > using the Exclamation mark: > > INSERT OR UPDATE INTO t (pk1, !pk2, !f1, !f2, f3, f4) VALUES (...); -- > Again update only f3 and f4 if the record already exists. > > (Adding the marker to a PK field is a no-op). > Escaping is not needed since a fieldname starting with the same marker > will be in the list of field-names, no ambiguity, and in the case where > a set of fields contain fields starting with both one and two markers > (for which the programmer should be shot, but let's assume it possible) > then the field can simply be enclosed in quotes as is the norm for > disambiguation in SQLite. This next example has fields named !f and !!f: > > INSERT OR UPDATE INTO t (pk1, pk2, !"!f", !!f) VALUES (...); -- Here > updating only !!f if the record already exists. > > > Personally, I'm partial to option A. > > I know it's a bit of work, but it seems less so than many of the other > additions - perhaps let's first have another show-of-hands to see if > this a real need, but it is asked for here more frequently than any > other feature (to my perception at least). > > > _______________________________________________ > sqlite-users mailing list > sqlite-users@mailinglists.sqlite.orghttp://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users _______________________________________________ sqlite-users mailing list sqlite-users@mailinglists.sqlite.org http://mailinglists.sqlite.org/cgi-bin/mailman/listinfo/sqlite-users