Подтвердить что ты не робот

Postgres 9. 5+: UPSERT возвращает количество обновленных и вставленных строк

Я получаю канонический пример:

 INSERT INTO user_logins (username, logins)
 VALUES ('Naomi',1),('James',1)
 ON CONFLICT (username)
 DO UPDATE SET logins = user_logins.logins + EXCLUDED.logins;

Но теперь мне также нужно знать:

  1. Сколько строк было вставлено
  2. Сколько строк было обновлено, поскольку существующие
  3. Сколько строк невозможно вставить из-за ограничений
  4. Если ограничение для последней строки не соблюдается, будут ли сохранены предыдущие вставленные/обновленные строки в БД?
4b9b3361

Ответ 1

Я не знаю, как еще вы можете понять, какое событие произошло. Вы должны посмотреть на значение xmax, если xmax = 0 означает, что была вставлена строка, другое значение xmax там было обновлено.

У меня плохой английский, и я попытаюсь показать пример.

create table test3(r1 text unique, r2 text);
\d+ test3
                       Table "public.test3"
 Column | Type | Modifiers | Storage  | Stats target | Description 
--------+------+-----------+----------+--------------+-------------
 r1     | text |           | extended |              | 
 r2     | text |           | extended |              | 
Indexes:
    "test3_r1_key" UNIQUE CONSTRAINT, btree (r1)

ВСТАВИТЬ

INSERT INTO test3 
VALUES('www7','rrr'), ('www8','rrr2') 
ON CONFLICT (r1) DO UPDATE SET r2 = 'QQQQ' RETURNING xmax;
 xmax 
------
    0
    0

Если вы попытаетесь вставить дубликат:

INSERT INTO test3 
VALUES('www7','rrr'), ('www8','rrr2') 
ON CONFLICT (r1) DO UPDATE SET r2 = 'QQQQ' RETURNING xmax;
   xmax    
-----------
 430343538
 430343538
(2 rows)

INSERT 0 2

Результат может быть обработан таким образом:
Вставка 1 новой и 1 повторяющейся строки

WITH t AS  (
  INSERT INTO test3 
  VALUES('www9','rrr'), ('www7','rrr2') 
  ON CONFLICT (r1) DO UPDATE SET r2 = 'QQQQ' RETURNING xmax
) 
SELECT COUNT(*) AS all_rows, 
       SUM(CASE WHEN xmax = 0 THEN 1 ELSE 0 END) AS ins, 
       SUM(CASE WHEN xmax::text::int > 0 THEN 1 ELSE 0 END) AS upd 
FROM t;

all_rows  | ins | upd 
----------+-----+-----
        2 |   1 |   1

см. 5.4. Системные столбцы и MVCC

Очень интересно, как можно более эффективно решить проблему