Reputation: 93
Lets say, there is a table with a simple numeric ID column with values 1 and 2. And there are few dozens of other tables, that have rows with ID = 1 referenced in their foreign keys. Is there any way to cascade update all those references to 2 without generating updates for all the referencing tables?
UPDATE to clarify it a bit further.
We got a dictionary table like that, called CompanyTypes
:
ID | Name
---------
1 | Bar
2 | Restaurant
And we have a bunch of tables referencing that dictionary in their FKs. For simplicity, lets go with one named Companies
:
ID | Name | Type
----------------------
1 | Cool bar | 1
2 | Not a bar | 2
And now there came an administrative decision that we no longer need bars as a distinct company type, and now all the bars have to be remapped to be restaurants without altering the db schema (so I can not add mapping table or something like that). Yes, I can write a query to generate queries to update each table individually (UPDATE Companies SET Type = 2 WHERE Type = 1
and so on), but is there any way to trick the db engine into doing it for me?
Upvotes: 2
Views: 828
Reputation: 19623
Try an anonymous code block to iterate over all tables that have a foreign key related to CompanyTypes
and concatenate the table name with an UPDATE
statement:
DO $$
DECLARE
row record;
BEGIN
FOR row IN SELECT DISTINCT fk_tco.table_name as fk_table_name
FROM information_schema.referential_constraints rco
JOIN information_schema.table_constraints fk_tco ON
rco.constraint_name = fk_tco.constraint_name AND
rco.constraint_schema = fk_tco.table_schema
JOIN information_schema.table_constraints pk_tco ON
rco.unique_constraint_name = pk_tco.constraint_name AND
rco.unique_constraint_schema = pk_tco.table_schema
WHERE pk_tco.table_name = 'companytypes'
ORDER BY fk_table_name
LOOP
EXECUTE format('UPDATE %s SET Type = 2 WHERE Type = 1',row.fk_table_name);
END LOOP;
END;
$$;
Demo: db<>fiddle
Upvotes: 2