插入或替换多行,但没有唯一键或主键

问题描述 投票:0回答:1

嗨,我在SQlite3上遇到以下问题

我有一张简单的桌子

CREATE TABLE TestTable (id INT, cnt INT);

表中已经有一些行。

我有一些要插入表中的数据:{{id0,cnt0),(id1,cnt1)...}

我想在ID冲突时将数据插入表中,更新TestTable.cnt = TestTable.cnt + value.cnt

((values.cnt是cnt0,cnt1 ...基本上是我要插入的数据)

***但是问题是,对id没有主要或唯一的约束,我不允许更改它!

我目前拥有的是:

在我的程序中,我遍历所有值

UPDATE TestTABLE SET count = count + value.cnt WHERE id = value.id;

if (sqlite3_changes() == 0)

INSERT INTO MyTable (id, cnt) values (value.id, value.cnt);

但是问题是,对于非常大的数据集,对每个数据条目执行2个查询会花费太长时间。我正在尝试将多个条目捆绑到一个电话中。

如果您对我的描述有疑问,请告诉我,谢谢您的帮助!

sql database sqlite rdbms
1个回答
0
投票

如果能够创建临时表,请执行以下操作。尽管这里没有显示,但我建议将所有这些都包装在事务中。即使您还可以添加临时唯一索引,此技术也可能会提高效率。 (在这种情况下,您可以在临时表中使用UPSERT和源数据。)

CREATE TEMP TABLE data(id INT, cnt INT);

现在将新数据插入临时表中,无论是通过使用主机语言数据库还是通过类似的方式制作插入语句

INSERT INTO data (id, cnt)
VALUES (1, 100),
       (2, 200),
       (5, 400),
       (7, 500);

现在使用单个UPDATE语句更新所有现有行。 SQLite没有方便的语法来连接表和/或为UPDATE语句提供源查询。但是,可以使用嵌套语句来提供类似的便利:

UPDATE TestTable AS tt
SET cnt = cnt + ifnull((SELECT cnt FROM data WHERE data.id == tt.id), 0)
WHERE tt.id IN (SELECT id FROM data);

请注意,这两个嵌套查询彼此独立。实际上,对于这种简单情况,可以完全消除WHERE子句并获得相同的结果。 WHERE子句只是为了提高效率,仅尝试更新匹配的ID。 SET子句中的另一个子查询也指定了id上的匹配项,但仅此一项仍将允许更新不匹配的行,默认为null值并转换为0(通过isnull()功能)。顺便说一句,如果没有isnull()函数,该总和将导致null并将覆盖非null值。

最后,仅插入不存在id值的行:

INSERT INTO TestTable (id, cnt)
SELECT data.id, data.cnt
FROM data LEFT JOIN TestTable
     ON data.id == TestTable.id
WHERE TestTable.id IS NULL;
© www.soinside.com 2019 - 2024. All rights reserved.