Image I have the following table: (in reality there are more columns)
user_id | product_id
---------|------------
1| 1
1| 2
1| 3
2| 2
2| 3
Basically, I need to copy all rows with user_id = 1
but change it to user_id = 3
:
user_id | product_id
---------|------------
1| 1
1| 2
1| 3
2| 2
2| 3
3| 1
3| 2
3| 3
1
create table clone_test( user_id integer, product_id integer);
insert into clone_test values (1,1), (1,2), (1,3), (2,2), (2,3);
insert into clone_test (select 3, product_id from clone_test where user_id =1);
select * from clone_test ;
user_id | product_id
---------+------------
1 | 1
1 | 2
1 | 3
2 | 2
2 | 3
3 | 1
3 | 2
3 | 3
4
copy all rows with user_id = 1 but change it to user_id = 3:
As already demonstrated by @Adrian Klaver, that’s a simple query with a constant in place of the user_id
:
demo at db<>fiddle
insert into your_table
select 3 as user_id, product_id
from your_table
where user_id=1;
Is there any way to do it without manually listing all other columns?
There is, but
- modern IDEs can typically be configured to identify your db schema, so they can add those columns on their own, without you having to type all of them out
- dynamic SQL can be used to query your
information_schema
to add those columns into your query, but that’s pretty ugly - both dynamic SQL and the
jsonb
trick are quite costly and ugly, so it’s better to make sure benefits of this justify that price
You can use auto-mapping Postgres does when converting records to and from jsonb
:
insert into clone_test
select (jsonb_populate_record( null::clone_test
,jsonb_set(to_jsonb(clone_test)
,'{user_id}'
,to_jsonb(3))
)
).*
from clone_test
where user_id=1;
to_jsonb()
grabs entire rows from the table and maps them tojsonb
.- In each,
jsonb_set()
changesuser_id
to a3
. jsonb_populate_record
maps the updatedjsonb
back to aclone_test
record.().*
unpacks the record, separating the columns.
Doing all that just to avoid having to tab through auto-completion, type out or copy the column list, is an overkill.