Simulating UPSERT was already discusssed before. In my case though, I have PRIMARY KEY and additional UNIQUE constraint, and I want upsert semantic with respect to primary key - replacing existing row if it exists, while checking the unique constraint.
Here's an attempt using insert-or-replace:
drop table if exists test;
create table test (id INTEGER, name TEXT, s INTEGER,
PRIMARY KEY (id, s),
UNIQUE (name, s));
insert or replace into test values (1, "a", 0);
insert or replace into test values (1, "a", 0);
insert or replace into test values (2, "b", 0);
insert or replace into test values (2, "a", 0);
The last statement is replaces both rows. This is documented behavior of 'insert or replace', but not what I want.
Here is an attempt with "on conflict replace":
drop table if exists test;
create table test (id INTEGER, name TEXT, s INTEGER,
PRIMARY KEY (id, s) on conflict replace,
UNIQUE (name, s));
insert into test values (1, "a", 0);
insert into test values (1, "a", 0);
I get "UNIQUE constraint failed" right away. The problem disappears if don't share column between both primary key and unique constraint:
drop table if exists test;
create table test (id INTEGER, name TEXT,
PRIMARY KEY (id) on conflict replace,
UNIQUE (name));
insert into test values (1, "a");
insert into test values (1, "a");
insert into test values (2, "b");
insert into test values (2, "a");
Here, I get constraint violation on the very last statement, which is precisely right. Sadly, I do need to share a column between constraints.
Is this something I don't understand about SQL, or SQLite issue, and how do I get the desired effect, except for first trying insert and then doing update on failure?