Правильное использование предложения SQLite ON CONFLICT - PullRequest
0 голосов
/ 18 февраля 2020

У меня есть база данных SQLite, которая, помимо прочего, имеет следующую таблицу:

CREATE TABLE IF NOT EXISTS biases
(
 data INTEGER NOT NULL,
 link INTEGER DEFAULT 0,
 bias_type INTEGER,
 ignores INTEGER DEFAULT 0,
 desists INTEGER DEFAULT 0,
 encashes INTEGER DEFAULT 0, 
 accesses INTEGER DEFAULT 0,
 scraps INTEGER DEFAULT 0,
 CONSTRAINT pk_bias_mix PRIMARY KEY(data,link,bias_type)
);  

Ограничение pk_bias_mix используется для обеспечения того, чтобы никакие две строки не могли иметь одинаковые значения для всех трех столбцы data, link и bias_type столбцы. Итак, предположим, что я

INSERT INTO biases (data,link,bias_type,ignores) VALUES(1,1,1,1);

работает так, как ожидалось - новая строка вставлена ​​в таблицу. Если я снова выдаю тот же INSERT, я получаю ошибку

UNIQUE CONSTRAINT FAILED: biases.data, biases.link, biases.bias_type

, как и ожидалось. Я попытался использовать предложение SQLite ON CONFLICT, таким образом

INSERT INTO biases (data,link,bias_type,ignores) VALUES(1,1,1,1)
ON CONFLICT(data,link,bias_type) DO UPDATE SET ignores = ignores + 1;

, и это сработало так, как я надеялся - вместо добавления новой строки или выдачи ошибки SQLite увеличил значение столбца ignores в строка с совпадающими значениями data, link и bias_type.

Однако это всего лишь результат эксперимента. Из документации по SQLite мне не сразу понятно, что именно так и должен себя вести ON CONFLICT, т. Е. Ему могут быть предоставлены два или более конфликтных ограничения для проверки. Под двумя или более ограничениями я подразумеваю указание нескольких столбцов, разделенных запятыми, внутри CONFLICT(...), как я делал в приведенном выше примере.

Я подозреваю, что это правильное использование, поскольку я просто указываю CONFLICT состояние, которое повторяет мое указанное CONSTRAINT. Тем не менее, я не вижу этого объяснения в явной форме нигде в документации. Я был бы очень признателен всем, кто мог бы подтвердить это.

1 Ответ

0 голосов
/ 18 февраля 2020

С UPSERT :

UPSERT - это специальное синтаксическое дополнение к INSERT, которое заставляет INSERT вести себя как UPDATE или no-op, если INSERT нарушает ограничение уникальности .

и:

Специальная обработка UPSERT происходит только для ограничения уникальности для таблицы, которая получает INSERT.

Таким образом, часть DO UPDATE не вызывается каким-либо конфликтом ограничений, а только уникальным нарушением ограничения.

Также:

Синтаксис, возникающий между ключевыми словами «ON CONFLICT» и «DO», называется «целью конфликта». Цель конфликта задает специфицирует c ограничение уникальности , которое вызовет переход.

Таким образом, невозможно иметь два или более ограничений конфликта быть проверенным в одном утверждении. Однако вы можете использовать отдельные операторы UPSERT, чтобы проверить наличие 2 различных уникальных нарушений ограничений. См. Упрощенную демоверсию , где я добавил еще 1 UNIQUE ограничение к вашей таблице:

CONSTRAINT con_scraps UNIQUE(scraps)
...