增量计数器或在一条语句中插入行,在SQLite中

增量计数器或在一条语句中插入行,在SQLite中,sql,sqlite,query-optimization,Sql,Sqlite,Query Optimization,在SQLite中,给定此数据库模式 CREATE TABLE observations ( src TEXT, dest TEXT, verb TEXT, occurrences INTEGER ); CREATE UNIQUE INDEX observations_index ON observations (src, dest, verb); 每当新的观察元组(:src,:dest,:verb)出现时,我想增加该元组现有行的“出现次数”列,或者添加一

在SQLite中,给定此数据库模式

CREATE TABLE observations (
    src TEXT,
    dest TEXT,
    verb TEXT,
    occurrences INTEGER
);
CREATE UNIQUE INDEX observations_index
    ON observations (src, dest, verb);
每当新的观察元组
(:src,:dest,:verb)
出现时,我想增加该元组现有行的“出现次数”列,或者添加一个出现次数为1的新行(如果还没有)。在具体的伪代码中:

if (SELECT COUNT(*) FROM observations
        WHERE src == :src AND dest == :dest AND verb == :verb) == 1:
    UPDATE observations SET occurrences = occurrences + 1
        WHERE src == :src AND dest == :dest AND verb == :verb
else:
    INSERT INTO observations VALUES (:src, :dest, :verb, 1)

我想知道是否有可能在一个SQLite语句中完成整个操作。这将简化应用程序逻辑(需要完全异步的wrt数据库操作),并避免使用完全相同的键进行双索引查找。INSERT或REPLACE似乎不是我想要的,可惜没有更新或INSERT。

不知道如何在一条语句中完成,但您可以尝试

BEGIN;
    INSERT OR IGNORE INTO observations VALUES (:src, :dest, :verb, 0);
    UPDATE observeraions SET occurrences = occurrences + 1 WHERE
        src = :src AND dest = :dest AND verb = :verb;
COMMIT;

我从Igor Tandetnik的sqlite用户那里得到了这个答案:

INSERT OR REPLACE INTO observations
VALUES (:src, :dest, :verb,
  COALESCE(
    (SELECT occurrences FROM observations
       WHERE src=:src AND dest=:dest AND verb=:verb),
    0) + 1);

它比dan04的方法稍微快一些,但始终快。

出现次数声明为整数不是更有意义吗?如果这是显而易见的,但别忘了根据OP创建一个唯一的索引,否则这将始终创建一个新计数器,并且永远不会递增:
create unique index observations\u index ON observations(src、dest、verb)。还要注意,它会在每次更新时增加ROWID(因为每次更新本质上都是DELETE+INSERT)。我想知道,这一次是否应该在事务中运行?