如何在不使用 CONFLICT_REPLACE 的情况下获得“插入或更新”行为?

Posted

技术标签:

【中文标题】如何在不使用 CONFLICT_REPLACE 的情况下获得“插入或更新”行为?【英文标题】:How do I get "insert or update" behaviour without using CONFLICT_REPLACE? 【发布时间】:2012-11-09 01:11:11 【问题描述】:

我的 android 应用使用 SQLite FTS3 表提供全文搜索。我正在使用 insertWithOnConflictCONFLICT_REPLACE 来更新我的数据库,如果需要插入新行或更新现有行(如果存在)。

我很惊讶地发现我的表最终包含重复的行 - 但看起来这是 SQLite 的 FTS 模块的文档化“功能”:

来自SQLite FTS3 and FTS4 Extensions 页面:

数据类型和列约束与每列一起指定。 FTS 和 SQLite 完全忽略了这些。

从命令行复制副本非常容易:

sqlite> CREATE VIRTUAL TABLE test_duplicates USING FTS3
   ...> (id INTEGER PRIMARY KEY, name TEXT);
sqlite> INSERT INTO test_duplicates (id, name) VALUES (1, "George");
sqlite> INSERT INTO test_duplicates (id, name) VALUES (1, "George");
sqlite> INSERT OR REPLACE INTO test_duplicates (id, name) VALUES (1, "George");
sqlite> SELECT * FROM test_duplicates;
1|George
1|George
1|George
sqlite>

我的问题是:复制CONFLICT_REPLACE 行为的最佳(最简单、最可靠)方法是什么?

我目前的想法是 (A) 执行 SELECT,然后根据结果执行 UPDATE 或 INSERT,或者 (B) 盲目尝试删除现有行(可能存在也可能不存在)然后 INSERT。

【问题讨论】:

【参考方案1】:

参考fts document,我找到了这一段:

...每个 FTS 表都有一个“rowid”列。 FTS 表的 rowid 与普通 SQLite 表的 rowid 列的行为方式相同,只是在使用 VACUUM 命令重建数据库时,FTS 表的 rowid 列中存储的值保持不变。对于 FTS 表,允许使用“docid”作为别名以及通常的“rowid”、“oid”和“oid”标识符。尝试使用表中已存在的 docid 值插入或更新行是错误的,就像使用普通 SQLite 表一样。

这意味着您可以使用内置的 docid 列作为主键,并让 fts 表对其应用它的约束。

【讨论】:

【参考方案2】:

我也有同样的问题。我发现当我们CREATE VIRTUAL TABLE test_duplicates USING FTS3 时,它会创建一个名为rowid 的列,它是该表的主键,因此我们只需要使用rowid 而不是id 就可以正常工作。

如果你改变: INSERT INTO test_duplicates (id, name) VALUES (1, "George");

到:

INSERT INTO test_duplicates (rowid, id, name) VALUES (1, 1, "George");
INSERT INTO test_duplicates (rowid, id, name) VALUES (2, 2, "George");

【讨论】:

【参考方案3】:

我不会因此而受到赞扬。但我找不到我从中得到的原始链接。 你做一个查询,然后:

if (cursor.moveToFirst()) 
        // record exists
     else 
        // record not found

【讨论】:

【参考方案4】:

我使用以下查询插入或替换

INSERT OR REPLACE INTO test_duplicates (`rowid`, `name`) VALUES 
((SELECT `rowid` FROM test_duplicates WHERE `name` = "George" LIMIT 1), "George")

而且它有效。但在这种情况下,您不能提供rowidrowid 将由数据库自己处理。

【讨论】:

以上是关于如何在不使用 CONFLICT_REPLACE 的情况下获得“插入或更新”行为?的主要内容,如果未能解决你的问题,请参考以下文章

如何在不安装 Zend 框架的情况下使用 Zend 库

如何在不更改链接结构的情况下使用 \ 转义字符 (、)、[、]、*、_、:[]()

如何在不使用 sleep() 的情况下使用 ontimer 函数延迟进程?

如何在不使用 Flexbox 的情况下水平对齐元素?

如何在不安装的情况下使用数据库?

如何在不使用滤镜的情况下使图像变暗? [复制]