当发生
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
解决方法是将列的定义更改为以下内容:
create table b (c1 integer primary key, c2 text UNIQUE ON CONFLICT IGNORE);
从你的
insert
中移除
或替换
条款;
然后在你的
insert
之后进行测试时,你需要执行以下的 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
第三个
insert
之后的更改返回值将是一个通知,告诉您的应用程序需要查找
"test-1"
的
rowid
,因为它已经存在于文件中。当然,如果这是一个多用户系统,您还需要将所有内容包装在一个事务中。
insert or replace into b values (1,'test-1');
我无法获取到(1,val)的数据,所以我使用了null。如果我尝试insert or replace into b (c2) values(val)
和insert or replace into b (c2) select val
,我会得到相同的结果。这是一个图片(为什么我不能在sqlite-shell中复制/粘贴!)http://i.imgur.com/2a6IY.png - user34537