2 years ago
#49048
Chad S
How to update all constraints referencing some field? For loop execute plpgsql
I want to update several constraints to cascade on delete or update. I know there are going to be major changes to "field_z" in "my_table", and many other fields in my database are foreign keys referencing "field_z" thus I need them to update automatically. The following two lines of code solve the problem for one constraint.
ALTER TABLE some_table DROP CONSTRAINT some_table_field_z_fkey
ALTER TABLE some_table ADD CONSTRAINT some_table_field_z_fkey FOREIGN KEY ('field_z') REFERENCES my_table ('field_z') ON DELETE CASCADE ON UPDATE CASCADE;
I need to update a large number of constraints. I'm using the code below to list all of the constraints and foreign keys tied to field_z in my_table.
CREATE TABLE temp_table AS (
select (select r.relname from pg_class r where r.oid = c.conrelid) as foreign_table,
(select attname from pg_attribute where attrelid = c.conrelid and ARRAY[attnum] <@ c.conkey) as foreign_col,
(select r.relname from pg_class r where r.oid = c.confrelid) as reference_table,
(select conname from pg_class r where r.oid = c.confrelid) as cnstrnt_name
from pg_constraint c
where c.confrelid = (select oid from pg_class where relname = 'my_table') and
c.confkey @> (select array_agg(attnum) from pg_attribute
where attname = 'field_z' and attrelid = c.confrelid)
);
I'd like to iterate through each row of the temp_table created above and substitute the cell values into the two lines of code at the top of this post, as shown below:
DO $$
DECLARE temp_row temp_table%ROWTYPE;
BEGIN
FOR temp_row in SELECT * FROM temp_table LOOP EXECUTE
'ALTER TABLE ' || quote_ident(temp_row.foreign_table) || ' DROP CONSTRAINT ' || quote_ident(temp_row.cnstrnt_name) || ';'
'ALTER TABLE ' || quote_ident(temp_row.foreign_table) || ' ADD CONSTRAINT ' || quote_ident(temp_row.cnstrnt_name) ||
' FOREIGN KEY (' || quote_ident(temp_row.foreign_col) || ')
REFERENCES ' || quote_ident(temp_row.reference_table) || ' (' || quote_literal(field_z) || ')
ON DELETE CASCADE ON UPDATE CASCADE;';
END LOOP;
END; $$ LANGUAGE plpgsql;
The for loop does not work, it breaks with error 'type "quote_ident" does not exist.' My hypothesis is that I haven't set up my loop to correctly iterate through rows and access the cell values as table, field, or constraint names. This is the first time I've used programmatic sql so I could be far off the mark. Any help to fix this loop or suggestions for better methods is appreciated. Thanks.
postgresql
plpgsql
0 Answers
Your Answer