Reputation: 19
i have a table with columns a,b,c and c having the unique key constraint.
a |b |c(uk)
----------
aa 1 z
I want to insert a new row with values (bb,1,z), if z already exists then i first want to update the existing row to
a |b |c(uk)
----------
aa 1 null
and then insert (bb,1,z), so that the final rows looks as shown below.
a |b |c(uk)
----------
aa 1 null
bb 1 z
how can i do this a single sql statement?
Upvotes: 0
Views: 1369
Reputation:
Unfortunately unique constraints are checked per row in Postgres - unless they are created as "deferrable".
So if you want to do the UPDATE and the INSERT in a single statement, you will have to re-create your unique constraint with the attribute deferrable. Then Postgres will check it at the end of the statement.
create table the_table
(
a text,
b int,
c text
);
alter table the_table
add constraint unique_c
unique(c)
deferrable --<< this is the "magic"
;
Then you can do it with a data modifying CTE
with input (a,b,c) as (
values ('bb', 1, 'z')
), change_old as (
update the_table
set c = null
from input
where input.c = the_table.c
)
insert into the_table
select a,b,c
from input;
Upvotes: 1
Reputation: 1630
I think you should use BEFORE INSERT TRIGGER for this.
In the trigger you would update all the records containing value new.c like:
UPDATE my_table SET
c = NULL
WHERE
c = new.c;
If c is not present - nothing will happen.
You may still run into unique constraint violation error if 2 concurent transactions inserts the same value into c. To avoid that you can use advisory locks providing lock ID from value of c.
Upvotes: 0