Увеличить счетчик или вставить строку в одном операторе в SQLite - PullRequest
15 голосов
/ 05 сентября 2010

В 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? Это упростит логику приложения (которая должна быть полностью асинхронной по отношению к операциям с базой данных), а также позволит избежать двойного поиска по индексу с точно таким же ключом. ВСТАВКА ИЛИ ЗАМЕНА, кажется, не то, что я хочу, и увы, нет ОБНОВЛЕНИЯ ИЛИ ВСТАВКИ.

Ответы [ 2 ]

12 голосов
/ 07 сентября 2010

Я получил ответ от Игоря Тандетника о sqlite-users:

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.

3 голосов
/ 06 сентября 2010

Не знаю, как это сделать в одном утверждении, но вы можете попробовать

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;
...