Sqlite插入带有唯一名称,获取id

时间:2009-05-10 07:42:48

标签: sqlite unique identity auto-generate

我有一个要插入数据库的字符串列表。它们必须是独一无二的。当我插入我想要他们的ID(用作另一个表中的外键)所以我使用last_insert_rowid。我遇到了2个问题。

  1. 如果我使用替换,他们的身份 (INTEGER PRIMARY KEY)更新哪些 打破我的数据库(条目指向 不存在的ID)
  2. 如果我使用ignore,则不会更新rowid,因此我没有获得正确的ID
  3. 我如何获得他们的ID?如果我不需要我不想使用select语句检查并插入字符串,如果它不存在。我该怎么做?

4 个答案:

答案 0 :(得分:8)

当发生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,因为它已经存档。当然,如果这是一个多用户系统,您还需要将所有这些包装在一个事务中。

答案 1 :(得分:3)

我目前使用以下

insert into tbl(c_name) select 'val' where not exists(select id from tbl where c_name ='val');
select id from tbl where c_name ='val';

答案 2 :(得分:1)

通过“它们必须是唯一的”,它们是否意味着你确定它们是,或者你想要一个错误,如果它们不是?如果您只是将字符串本身作为其表中的一个键,那么我不明白1或2是如何成为问题的 - 如果出现不需要的重复,您将得到所需的错误,否则正确的ID。也许您可以使用您正在使用的SQL代码的一个小示例,您正在观察的行为以及您想要的行为来澄清您的问题......?

编辑:感谢编辑,但我仍然不清楚SQL给你带来了什么问题!如果你的表来自,例如:

CREATE TABLE Foo(
  theid INTEGER PRIMARY KEY AUTOINCREMENT,
  aword TEXT UNIQUE ABORT
  )

然后任何插入重复单词的尝试都将失败(ABORT关键字是可选的,因为它是UNIQUE的默认值) - 不是你想要的假设你说的话“必须是唯一的”,即如果它们不是,那就错了吗?

答案 3 :(得分:0)

您的问题的正确答案是:这不能在 sqlite 中完成。您必须进行额外的选择查询。为 last_insert_rowid 引用 docs

<块引用>

由于违反约束而失败的 INSERT 不是成功的 INSERT,并且不会更改此例程返回的值。因此,INSERT OR FAIL、INSERT OR IGNORE、INSERT OR ROLLBACK 和 INSERT OR ABORT 在插入失败时不会更改此例程的返回值