Когда происходит нарушение ограничения UNIQUE, алгоритм REPLACE удаляет ранее существующие строки, которые вызывают нарушение ограничения, перед вставкой или обновлением текущей строки, и команда продолжает нормально выполняться. Это приводит к изменению rowid и создает следующую проблему
Y:> **sqlite3 test**
SQLite version 3.7.4
Enter ".help" for instructions
Enter SQL statements terminated with a ";"
sqlite> **create table b (c1 integer primary key, c2 text UNIQUE);**
sqlite> **insert or replace into b values (null,'test-1');**
sqlite> **select last_insert_rowid();**
1
sqlite> **insert or replace into b values (null,'test-2');**
sqlite> **select last_insert_rowid();**
2
sqlite> **insert or replace into b values (null,'test-1');**
sqlite> **select last_insert_rowid();**
3
sqlite> **select * from b;**
2|test-2
3|test-1
Обходной путь - изменить определение столбца c2 следующим образом
create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);
и удалить из ваших вставок предложение «или заменить»;
тогда при тестировании после вставки вам нужно будет выполнить следующий sql: select last_insert_rowid(), changes();
sqlite> **create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);**
sqlite> **insert into b values (null,'test-1');**
sqlite> **select last_insert_rowid(), changes();**
1|1
sqlite> **insert into b values (null,'test-2');**
sqlite> **select last_insert_rowid(), changes();**
2|1
sqlite> **insert into b values (null,'test-1');**
sqlite> **select last_insert_rowid(), changes();**
2|0
Возвращаемым значением изменений после 3-й вставки будет уведомление вашего приложения о том, что вам нужно будет найти идентификатор строки «test-1», поскольку он уже был в файле. Конечно, если это многопользовательская система, вам нужно будет также обернуть все это в транзакцию.