Использование second WHERE
сделает то, что вы хотите:
INSERT INTO actions(name) VALUES ('bla');
INSERT INTO actions(name, value) VALUES ('bla', 'val1')
ON CONFLICT(name) DO UPDATE SET value = excluded.value WHERE value IS NULL;
SELECT * FROM actions;
name value
---------- ----------
bla val1
INSERT INTO actions(name, value) VALUES ('bla', 'val2')
ON CONFLICT(name) DO UPDATE SET value = excluded.value WHERE value IS NULL;
SELECT * FROM actions;
name value
---------- ----------
bla val1
Первый WHERE
после столбца (-ов) конфликта предназначен для выбораконкретный частичный индекс, чтобы использовать для обнаружения конфликтов. Вот пример того, как вы это чувствуете:
sqlite> CREATE TABLE ex(name, value1, value2);
sqlite> CREATE UNIQUE INDEX ex_idx_name ON ex(name) WHERE value1 IS NULL;
sqlite> INSERT INTO ex(name) VALUES ('bla');
sqlite> INSERT INTO ex(name, value2) VALUES ('bla', 'val1');
Error: UNIQUE constraint failed: ex.name
sqlite> INSERT INTO ex(name, value1, value2) VALUES ('bla', 1, 'val2');
sqlite> SELECT * from ex;
name value1 value2
---------- ---------- ----------
bla (null) (null)
bla 1 val2
sqlite> INSERT INTO ex(name, value2) VALUES ('bla', 'val3')
...> ON CONFLICT(name) WHERE value1 IS NULL DO UPDATE SET value2 = excluded.value2;
sqlite> SELECT * from ex;
name value1 value2
---------- ---------- ----------
bla (null) val3
bla 1 val2
sqlite> INSERT INTO ex(name, value2) VALUES ('bla', 'val4')
...> ON CONFLICT(name) DO UPDATE SET value2 = excluded.value2;
Error: ON CONFLICT clause does not match any PRIMARY KEY or UNIQUE constraint
Обратите внимание, в частности, на два последних INSERT
s: первый обновляет строку с нулевым значением, а второй генерирует ошибку, потому что онне полностью указывает уникальный индекс.