当发生 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
第三次插入后更改的返回值将通知您的应用程序,您需要查找“test-1”的rowid,因为它已经在文件中。当然,如果这是一个多用户系统,您也需要将所有这些都包装在一个事务中。