2016-08-09 83 views
8

ich die kanonische Beispiel erhalten zurückzukehren:Postgres 9.5+: UPSERT die Anzahl der aktualisierten und eingefügten Zeilen

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

Aber jetzt weiß ich, müssen auch:

  1. Wie viele Zeilen
  2. eingefügt wurden
  3. Wie viele Zeilen wurden, weil
  4. bestehende aktualisiert Wie viele Zeilen nicht wegen der Beschränkungen eingeführt werden könnte
  5. Wenn t Wird die Einschränkung für die letzte Zeile nicht beachtet, werden die vorherigen eingefügten/aktualisierten Zeilen in der DB beibehalten?

Antwort

4

Ich weiß nicht, wie sonst Sie verstehen können, welches Ereignis aufgetreten ist. Sie sollten sich den Wert von xmax ansehen, wenn xmax = 0 bedeutet, dass Zeile eingefügt wurde, anderer Wert xmax dort Zeile wurde aktualisiert.

Ich habe schlecht Englisch und ich werde versuchen, das Beispiel zu zeigen.

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

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

Wenn Sie versuchen, ein Duplikat einzufügen:

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 

Das Ergebnis kann in einer solchen Art und Weise bearbeitet werden:
einlegen 1 neu und 1 doppelte Zeilen

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 

siehe 5.4. System Columns und MVCC

Sehr interessant, wie das Problem mehr lösen kann anmutig