In short, I am trying to do this:
Setup:
create table info(
info_id serial primary key,
info_text text
);
create table product(
prod_id serial primary key,
info_id int /*unique*/,
description text unique,
price int);
insert into product (description, price) values ('pen', 1), ('notebook', 2), ('ruller', 3);
Now I am trying to update all product
rows where the info_id
reference is null
, by way of creating a new row in the info
table and then assign the reference to it to the product:
with new_info as (insert into info default values returning info_id)
update product
set info_id = (select info_id from new_info)
where product.info_id is null;
The problem is that it only creates one info and then assigns all products to it. I expect it to create one companion info row for each product.
select * from product, info where product.info_id = info.info_id;
prod_id | info_id | description | price | info_id | info_text
---------+---------+-------------+-------+---------+-----------
1 | 1 | pen | 1 | 1 | [null]
2 | 1 | notebook | 2 | 1 | [null]
3 | 1 | ruller | 3 | 1 | [null]
This creates a separate new row in table info
and backfills a reference to it for every null in product.info_id
:
WITH upd AS (
UPDATE product
SET info_id = nextval(pg_get_serial_sequence('info', 'info_id'))
WHERE info_id IS NULL
RETURNING info_id
)
INSERT INTO info (info_id)
SELECT info_id
FROM upd;
Even works with a FK constraint in place.
Related: