Инкремент счетчика или вставка строки в одном выражении, в SQLite
В 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. Это упростило бы логику приложения (которая должна быть полностью асинхронной по отношению к операциям базы данных), а также избежать двойного поиска индекса с помощью одного и того же ключа. INSERT или REPLACE, похоже, не то, что я хочу, и, увы, нет UPDATE ИЛИ INSERT.
Ответы
Ответ 1
Я получил ответ от Игоря Тандетника на пользователя 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.
Ответ 2
Не знаю способа сделать это в одном утверждении, но вы можете попробовать
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;