Postgresql: ON CONFLICT UPDATE, только если было предоставлено новое значение - PullRequest
0 голосов
/ 11 марта 2020

У меня есть эта таблица:

CREATE TABLE myTable (
  a VARCHAR(32),
  b VARCHAR(32) DEFAULT NULL,
  c VARCHAR(32) DEFAULT NULL,

  PRIMARY KEY (a)
);

и запрос типа "UPSERT":

INSERT INTO 
  myTable ( a,  b,  c)
  VALUES  ($1, $2, $3)
ON CONFLICT (a)
  DO UPDATE SET
    b = $2,
    c = $3,
RETURNING
  a, b, c
;

Это работает, как и ожидалось. Если я сначала вставлю (json для удобства записи):

{a:"a", b:"b", c:"c"}

, тогда я смогу обновить его с помощью таких параметров:

{a:"a", b:"x", c:"y"}

И я получу ожидаемый результат - Запись {a: "a"} обновила столбцы b и c.

Но я также хотел бы сделать это:

{a:"a", c:"Q"}

и обновить c столбец , оставляя столбец b нетронутым.

Конечно, мне нужно какое-то выражение с правой стороны, но я не знаю что это такое Моя интуиция выглядит примерно так (SQL псевдокод):

...
  DO UPDATE SET
    b = ($2 | b)
    c = ($3 | c)
...

Какой здесь правильный синтаксис? Или я должен использовать совершенно другой метод?

1 Ответ

0 голосов
/ 11 марта 2020

Вы можете использовать COALESCE(). Идея состоит в том, чтобы передать значение NULL одному из параметров, и тогда вы можете сделать:

INSERT INTO myTable (a,  b,  c)
VALUES  ($1, $2, $3) 
DO UPDATE SET
    b = COALESCE(EXCLUDED.b, b)
    c = COALESCE(EXCLUDED.c, c)

Когда запись уже существует с a = $1 и $1 или $2 присваивается значение null, а затем записывается только значение, отличное от null.

Недостатком является то, что этот запрос не сможет присвоить значение null для уже существующей записи.

Примечание: при этом вместо повторения используется псевдотаблица EXCLUDED параметры.

...