简体   繁体   中英

How to update on conflict postgres

I have sql statement

create table test
(
    code   varchar,
    date   date,
    code_2 varchar(2),
    type   varchar(4),
    sum    int default 1
);

alter table test
    add primary key (code, date, type);

insert into test(code, date, code_2, type)
select (array ['abc', 'xyz'])[ceil(random() * 2)],
       (array ['2021-05-28', '2021-05-27'])[ceil(random() * 2)]::date,
       (array ['qq', 'ee'])[ceil(random() * 2)],
       (array ['ABCD', 'DCBA'])[ceil(random() * 2)]
from generate_series(1, 1000)
on conflict (code, date, type)
    do update set sum = excluded.sum + 1;

I want to add a record and sum it on (a group code, date, type) if it exist, if it's not, add new record

but above sql do not run and the error

ERROR: ON CONFLICT DO UPDATE command cannot affect row a second time

The error message says it all. Change the SELECT so that it aggregates all rows with the same key:

INSERT INTO test(code, date, code_2, type, sum)
SELECT (array ['abc', 'xyz'])[ceil(random() * 2)],
       (array ['2021-05-28', '2021-05-27'])[ceil(random() * 2)]::date,
       max((array ['qq', 'ee'])[ceil(random() * 2)]),
       (array ['ABCD', 'DCBA'])[ceil(random() * 2)],
       count(*)
FROM generate_series(1, 1000)
GROUP BY 1, 2, 4
ON CONFLICT (code, date, type)
    DO UPDATE SET sum = test.sum + excluded.sum;

You don't need on conflict for this. Instead, generate the data using a CTE. Then aggregate it for insert:

with to_insert as (
       select (array ['abc', 'xyz'])[ceil(random() * 2)] as code,
              (array ['2021-05-28', '2021-05-27'])[ceil(random() * 2)]::date as date,
              (array ['qq', 'ee'])[ceil(random() * 2)] as code_2,
              (array ['ABCD', 'DCBA'])[ceil(random() * 2)] as type
       from generate_series(1, 1000)
      )
insert into test(code, date, code_2, type, sum)
    select code, date, min(code_2), type, count(*)
    from to_insert
    group by code, date, type;

Here is a db<>fiddle.

Notes:

  • You can still use on conflict if the table has existing data. It is just not needed for this example.
  • I suspect that you want code_2 in the primary key. The above logic just chooses the maximum value.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM