Thread: how to return data from insert into ... on conflict ... returning ... into
drop table if exists tbl;
drop sequence if exists seq;
create sequence seq;
create table tbl(
id int8 not null primary key,
d bytea not null,
h bytea not null, -- hash of the data, calculated automatically
dummy byte default 0 -- dummy value, see below...
);
alter table tbl add constraint uidx_tbl_h unique(h);
create or replace function trg() returns trigger language plpgsql as
$function$
begin
new.h = sha256(new.d); -- auto-hash
if new.id is null then
new.id = nextval('seq');
end if;
return new;
end;
$function$;
create trigger trg before insert or update on tbl for each row execute procedure trg();
do
$body$
declare
aid int8;
begin
insert into tbl(d) values ('1') returning id into aid; -- ok
raise notice '1->%', aid; -- ok
insert into tbl(d) values ('2') returning id into aid; -- ok
raise notice '2->%', aid; -- ok
insert into tbl(d) values ('1') on conflict(h) do update set dummy=0 returning id into aid; -- ok;
raise notice '1->%', aid; -- ok
insert into tbl(d) values ('2') on conflict(h) do update set dummy=0 returning id into aid; -- ok;
raise notice '2->%', aid; -- ok
end;
$body$;
delete from tbl;
do
$body$
declare
aid int8;
begin
insert into tbl(d) values ('1') returning id into aid; -- ok
raise notice '1->%', aid; -- ok
insert into tbl(d) values ('2') returning id into aid; -- ok
raise notice '2->%', aid; -- ok
insert into tbl(d) values ('1') on conflict(h) do nothing returning id into aid; -- ok;
raise notice '1->%', aid; -- null ??????
insert into tbl(d) values ('1') on conflict(h) do nothing returning id into aid; -- ok;
raise notice '2->%', aid; -- null ??????
end;
$body$;
delete from tbl;
do
$body$
declare
aid int8;
begin
insert into tbl(d) values ('1') returning id into aid; -- ok
raise notice '1->%', aid; -- ok
insert into tbl(d) values ('2') returning id into aid; -- ok
raise notice '2->%', aid; -- ok
select id from tbl into aid where h = sha256('1');
if not found then
insert into tbl(d) values ('1') on conflict(h) do update set id=id+0 returning id into aid;
end if;
raise notice '1->%', aid; -- null ??????
select id from tbl into aid where h = sha256('2');
if not found then
insert into tbl(d) values ('2') on conflict(h) do update set id=id+0 returning id into aid;
end if;
raise notice '2->%', aid; -- null ??????
end;
$body$;
Re: how to return data from insert into ... on conflict ... returning ... into
On Tue, Jun 20, 2023 at 1:26 PM Les <nagylzs@gmail.com> wrote: > > https://www.postgresql.org/docs/current/sql-insert.html#SQL-ON-CONFLICT > > and the only possible actions are "do nothing" and "do update". The "do nothing" does not update the record, that is clear.But it also does not return any data, and that was not obvious to me. Why can't it return the data from the conflictedrecord? After the instruction is completed, "GET DIAGNOSTICS" could still be used to check the number of updates. Would it be fair to summarize that you'd like a feature where, upon conflict, the command behaves as SELECT, and returns row that caused the conflict? The docs say: "If the INSERT command contains a RETURNING clause, the result will be similar to that of a SELECT statement containing the columns and values defined in the RETURNING list, computed over the row(s) inserted or updated by the command." So in your desired behaviour, the RETURNING list would be computed over the rows that cause the conflict. > I understand that changing this behaviour may break backward compatibility. Would it be possible to introduce a "DO RETURN"clause that returns the data, even when there was a conflict? If this behaviour is introduced with a new syntax, then there won't be any fears of breaking backwards compatibility. I think DO SELECT as the new syntax will make the intent clear. Taking one of your queries as an example, after the new syntax it will look as follows: insert into tbl(d) values ('1') on conflict(h) DO SELECT returning id into aid; Best regards, Gurjeet http://Gurje.et