Reputation: 25929
I've got a simple table:
CREATE TABLE ChecklistStep (
Checklist INTEGER REFERENCES Checklist (Id),
Id INTEGER PRIMARY KEY AUTOINCREMENT,
StepIndex INTEGER NOT NULL,
Name VARCHAR NOT NULL,
UNIQUE (Checklist, StepIndex));
Now I want to exchange two items' indexes. Doing so I'm breaking temporarily uniqueness of pair (Checklist, StepIndex). I hoped, that I can do that in transaction, such that after committing, all constraints will be kept, but this doesn't work:
begin transaction;
update ChecklistStep set StepIndex = 0 where id = 6;
update ChecklistStep set StepIndex = 1 where id = 5;
commit transaction;
Causes:
UNIQUE constraint failed: ChecklistStep.Checklist, ChecklistStep.StepIndex
How to write such update?
Upvotes: 5
Views: 1786
Reputation: 180270
SQLite does not have deferred UNIQUE constraints.
The PRAGMA writable_schema dirty trick does not work here because the internal index would get corrupted if you changed the table without updating the index.
The only way to do this is to use a temporary value that is guaranteed to be unused:
begin;
update ChecklistStep set StepIndex = -99999999 where id = 6;
update ChecklistStep set StepIndex = 1 where id = 5;
update ChecklistStep set StepIndex = 0 where id = 6;
commit;
Upvotes: 7