I get the canonical example:
INSERT INTO user_logins (username, logins)
VALUES ('Naomi',1),('James',1)
ON CONFLICT (username)
DO UPDATE SET logins = user_logins.logins + EXCLUDED.logins;
But now I also need to know:
PostgreSQL lets you either add or modify a record within a table depending on whether the record already exists. This is commonly known as an "upsert" operation (a portmanteau of "insert" and "update").
In PostgreSQL, the UPSERT operation means either UPDATE or INSERT operation. The UPSERT operation allows us to either insert a row or skip the insert operation if a row already exists and update that row instead. Suppose you want to insert bulk data from one table to another table that already has some data.
A relational database management system uses SQL MERGE (also called upsert) statements to INSERT new records or UPDATE existing records depending on whether condition matches. It was officially introduced in the SQL:2003 standard, and expanded in the SQL:2008 standard.
OID is an object identifier. PostgreSQL used the OID internally as a primary key for its system tables. Typically, the INSERT statement returns OID with value 0. The count is the number of rows that the INSERT statement inserted successfully.
I do not know how else you can understand what event occurred. You should look at the value of xmax, if xmax = 0 means there row was inserted, other value xmax there row was update.
I have bad English and I will try to show the example.
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
If you try to insert a duplicate:
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
The result can be processed in such a way:
Inserting 1 new and 1 duplicate rows
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
see 5.4. System Columns and MVCC
Very interesting how can solve the problem more gracefully
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With