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);
挿入から「or replace」句を削除します。
挿入後にテストするときは、次の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」の行 ID が既にファイルにあるため、その行 ID を検索する必要があることをアプリケーションに通知します。もちろん、これがマルチユーザー システムの場合は、これもすべてトランザクションでラップする必要があります。